{"id":19848119,"url":"https://github.com/shunnnet/co","last_synced_at":"2026-02-23T23:34:25.751Z","repository":{"id":243474609,"uuid":"810954586","full_name":"shunnNet/co","owner":"shunnNet","description":"✨ A front-end development AI writing assistant, similar to Copilot but with a different working approach, will automatically create and write the content of the referenced files in the code.","archived":false,"fork":false,"pushed_at":"2025-02-09T15:34:25.000Z","size":397,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-01T08:33:49.769Z","etag":null,"topics":["ai","frontend","llm","react","vite","vue"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shunnNet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-06-05T17:00:10.000Z","updated_at":"2025-02-09T15:34:28.000Z","dependencies_parsed_at":"2024-07-07T08:52:53.952Z","dependency_job_id":"e4628774-6bcd-4e53-a97d-e6613d2bc134","html_url":"https://github.com/shunnNet/co","commit_stats":null,"previous_names":["shunnnet/co","imaginary-co/co"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/shunnNet/co","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shunnNet%2Fco","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shunnNet%2Fco/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shunnNet%2Fco/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shunnNet%2Fco/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shunnNet","download_url":"https://codeload.github.com/shunnNet/co/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shunnNet%2Fco/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29760682,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-23T21:02:23.375Z","status":"ssl_error","status_checked_at":"2026-02-23T20:58:31.539Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","frontend","llm","react","vite","vue"],"created_at":"2024-11-12T13:16:12.772Z","updated_at":"2026-02-23T23:34:25.733Z","avatar_url":"https://github.com/shunnNet.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ✨ co\n\u003e [!WARNING]\n\u003e This project is still in development, but you can try out some features.\n\nA front-end development AI writing assistant, similar to Copilot but with a different working approach, will automatically create and write the content of the referenced files in the code.\n\n- [✨ co](#-co)\n  - [Features](#features)\n  - [Demo](#demo)\n    - [Vue - Write a simple page](#vue---write-a-simple-page)\n    - [Vue - Write autocomplete input](#vue---write-autocomplete-input)\n    - [Markdown: Generate a project](#markdown-generate-a-project)\n    - [TDD](#tdd)\n  - [Quick start](#quick-start)\n  - [Usage](#usage)\n  - [Tutorial \\\u0026 Examples](#tutorial--examples)\n    - [`@co:`](#co)\n    - [Comment: provide more hint](#comment-provide-more-hint)\n    - [Reference from multiple place](#reference-from-multiple-place)\n    - [`@co-source:`](#co-source)\n    - [Supported File Types and Comments](#supported-file-types-and-comments)\n      - [Javascript](#javascript)\n      - [Markdown](#markdown)\n  - [Markdown](#markdown-1)\n  - [Why `Co` ?](#why-co-)\n    - [Small Issues with Copilot](#small-issues-with-copilot)\n    - [How Co Is Different](#how-co-is-different)\n    - [How Does Co Work?](#how-does-co-work)\n    - [Use Cases and Potential of Co](#use-cases-and-potential-of-co)\n      - [Prototyping](#prototyping)\n      - [TDD (Test-Driven Development)](#tdd-test-driven-development)\n  - [Additional: `aicss` (Experimental)](#additional-aicss-experimental)\n  - [License](#license)\n\n## Features\n- ✨ Auto write/rewrite when you import a module (with special comments)\n- 🌴 Generate a project by markdown\n- 🛠️ TDD: auto generate implementation when writing test cases.\n\n## Demo\nUsing OpenAI `gpt-4o-mini`\n\n### Vue - Write a simple page\n[![Vue demo](https://i.ytimg.com/vi/IGBJbUESEtk/maxresdefault.jpg)](https://youtu.be/IGBJbUESEtk) \n\n### Vue - Write autocomplete input\n[![AutoComplete demo](https://i.ytimg.com/vi/Hfavj2m1o1s/maxresdefault.jpg)](https://youtu.be/Hfavj2m1o1s) \n\n### Markdown: Generate a project\n[![Markdown demo](https://i.ytimg.com/vi/4XRZIQb3YOk/maxresdefault.jpg)](https://youtu.be/4XRZIQb3YOk) \n\n### TDD\n[![TDD demo](https://i.ytimg.com/vi/cWDb-U3fImM/maxresdefault.jpg)](https://youtu.be/cWDb-U3fImM) \n\n## Quick start\nInstall the package.\n\n```sh\nnpm install @imaginary-ai/core\n```\n\nCreate `co.config.{js|ts}` in current working directory.\n\n```ts\n// co.config.ts\nimport { OpenAITextGenerator, defineCoConfig } from '@imaginary-ai/core'\n\nexport default defineCoConfig({\n  baseDir: '.',\n  includes: ['**/*.js', '**/*.ts', '**/*.md'],\n  excludes: ['**/node_modules/**', '**/.vscode', '**/.git/**', '**/ai.css'],\n  generator: new OpenAITextGenerator({\n    apiKey: '...', // Put your OPENAI_API_KEY here\n    model: 'gpt-4o-mini',\n    temperature: 0,\n  }),\n})\n```\n\nWrite some code import a function:\n```ts\n// @co:\nimport { sayHello } from \"./path-to-file.js\"\n// @co-end\n\nsayHello()\n```\n\nGo to terminal run `npx co run`, then `path-to-file.js` will be generated.\n\n```ts\n// path-to-file.js\nexport function sayHello() {\n    console.log(\"Hello, World!\");\n}\n```\n\n## Usage\n`Co` uses a glob pattern to scan files. If a file contains a co comment (e.g: `// @co:` and `// @co-end`), it will generate the files imported between the comments.\n\n- `npx co run`: Scans and generates files.\n- `npx co watch`: Scans and watches files based on the glob pattern. When a file containing a co comment is modified or added, it generates the files imported between the comments.\n- `npx co clear`: Removes all co comments (excluding the content between the comments).\n\nTo use the co command, a `co.config.ts` file must be present in the current working directory.\n\nYou can set `CO_CONFIG_PATH` env variable to change path-to-co-config, e.g: `CO_CONFIG_PATH=/user/name/co.config.ts npx co watch`\n\nTo see the prompt `Co` send to model, set environment variable `CONSOLA_LEVEL=4`, e.g: `CONSOLA_LEVEL=4 npx co run`.\n\n\u003e [!WARNING]\n\u003e Use `npx co watch` carefully. There is a possibility of causing infinite model calls. This issue has been addressed, but to prevent any unexpected situations, it is recommended to monitor the terminal while using the command to see if it keeps running continuously.\n\n## Tutorial \u0026 Examples\n\n### `@co:`\nThe files imported between `// @co:` and `// @co-end` will be automatically generated and can be single or multiple.\n\n```ts\n// @co:\nimport { add } from \"./math.js\"\nimport { isArray } from \"./utils.js\"\n// @co-end\n\nisArray(add(1,2,3,4,5)) // false\n```\n\nWhen generating file content, the model will generate the file based on how the imported module is used.\n\nShould generate `add` in `./math.js`, `isArray` in `./utils.js`. For example:\n\n```ts\n// math.js\nexport function add(...numbers) {\n    return numbers.reduce((sum, number) =\u003e sum + number, 0);\n}\n```\n```ts\n// utils.js\nexport function isArray(value) {\n    return Array.isArray(value);\n}\n```\n\nWhen you don't need to generate files, move the import out of the comment.\n\n```ts\n// @co:\n// @co-end\nimport { add } from \"./math.js\"\nimport { isArray } from \"./utils.js\"\n\nisArray(add(1,2,3,4,5)) // false\n```\n\nOr run `npx co clear`. After ran:\n\n```ts\nimport { add } from \"./math.js\"\nimport { isArray } from \"./utils.js\"\n\nisArray(add(1,2,3,4,5)) // false\n```\n\n\u003e [!NOTE] \n\u003e File extension in `./math.js` is required. Or it will generate `.ts` file by default. (e.g: `./math` will generate `./math.ts`)\n\n### Comment: provide more hint\nAdding comments appropriately in usage locations can provide more hints to the model, potentially improving accuracy.\n\nIt's like collaborating with another engineer—they will follow your comments and usage patterns to create the module you want.\n\n```ts\n// @co:\nimport { sayHello } from \"./utils.js\"\n// @co-end\n\nsayHello(\"Net\") // Net: Hello!\nsayHello(\"Net\", \"Foo\") // Net: Hello!\\nFoo: Hello!\n```\n\n### Reference from multiple place\nYou can reference the same file from multiple places, just like you would import the same module from multiple locations.\n\nIn this case, the model will consider usage from all locations and generate the corresponding file content.\n\n```ts\n// file: test.js\n// @co:\nimport { add } from \"./math.js\"\n// @co-end\n\nadd(1,2,3,4,5) // 15\n```\n\n```ts\n// file: test2.js\n// @co:\nimport { substract } from \"./math.js\"\n// @co-end\n\nsubstract(5,1) // 4\n```\n\nShould generate something like:\n\n```ts\n// math.js\nexport function substract(a, b) {\n    return a - b;\n}\n\nexport function add(...numbers) {\n    return numbers.reduce((sum, number) =\u003e sum + number, 0);\n}\n```\n\n### `@co-source:`\nSometimes, importing may not effectively point to the corresponding file. In such cases, you can use @co-source: to specify a path. When generating that path, the code between `@co-source:` and `@co-end` will be used as context.\n\nFor example, in the following case, `./module/math.js` will be generated relative to the current file.\n```ts\nimport { add } from \"./module\"\n\n// @co-source: path=./module/math.js\nadd(1,2,3,4,5) // 15\n// @co-end\n```\n\n`@co-source` can be used together with `@co`, and multiple groups can reference the same file simultaneously.\n\n### Supported File Types and Comments\n\n#### Javascript\nCurrently, comments in the following file types will be used as sources:\n`ts`, `tsx`, `js`, `jsx`, `cjs`, `mjs`, `vue`.\n\nIn these files, the following types of comments can be included:\n\n```ts\n// @co:\n...\n// @co-end\n\n// @co-source: path=./path-to-file\n...\n// @co-end\n```\n\n#### Markdown\nAlso support `.md` file. In markdown file, the following types of comments can be included:\n\n```md\n\u003c!-- @co: --\u003e\n...\n\u003c!-- @co-end --\u003e\n```\n\n## Markdown\nGeneration can be done through Markdown files(`.md`), where link references between comments will be generated. Currently, only one reference format is supported: `[text](link)`.\n\n```md\n\u003c!-- README.md --\u003e\nHere is the directory structure of our project:\n\n\u003c!-- @co: --\u003e\n`[index.js](./index.js)`: Starts an Express server and listens on port 3000.\n`[handler.js](./handler.js)`: Contains all request handlers under the `/api` route. It is imported by `index.js` and mounted onto Express.\n\u003c!-- @co-end --\u003e\n```\n\nMay generate files like:\n\n```js\n// index.js\nconst express = require('express');\nconst app = express();\nconst port = 3000;\nconst handler = require('./handler');\n\napp.use('/api', handler);\n\napp.listen(port, () =\u003e {\n    console.log(`Server is running at http://localhost:${port}`);\n});\n```\n\n```js\n// handler.js\nconst express = require('express');\nconst router = express.Router();\n\n// Example request handler for GET /api/example\nrouter.get('/example', (req, res) =\u003e {\n    res.json({ message: 'This is an example response' });\n});\n\n// Add more request handlers as needed\nrouter.get('/another-example', (req, res) =\u003e {\n    res.json({ message: 'This is another example response' });\n});\n\nmodule.exports = router;\n```\n\n\n## Why `Co` ?\n\n### Small Issues with Copilot\nI believe many people have used `GitHub Copilot` or similar code assistants. Personally, I use `GitHub Copilot`.\n\nThe feature I use most frequently in `GitHub Copilot` is autocomplete. While editing a file, the model predicts the next content and provides suggestions.\n\nThis truly deserves the name Copilot—it always lends a helping hand just when you’re feeling exhausted from coding. I often find myself genuinely grateful for it in those moments. At this point, I’ve gotten so used to autocomplete suggestions that it feels strange when they don’t appear.\n\nWithin a single file, it often does a good job predicting what I need. However, things get a bit awkward when working across multiple files.\n\nFor example, while writing File A, I realize I need a File B containing some functions to complete my work in File A.\n\nWith `GitHub Copilot`:\n\n1. It's best to have two tabs open simultaneously—one for File A and one for File B—to provide the model with the correct context (which might mean closing all other tabs first).\n2. Switch to File B and write the functions I need. (If lucky, Copilot might guess what I want and autocomplete them for me.)\n3. I return to File A and import the functions from File B.\n\nIf your Copilot behaves like mine, it’s probably most helpful in step 3, when it knows which functions you are trying to use. When I am editing File B, it is harder for Copilot to infer what I want to write based on File A.\n\nAdditionally, this disrupts my work in File A. Can it be made even smoother?\n\n### How Co Is Different\nI imagined a different kind of Copilot: one that doesn't just autocomplete within a single file but also understands your intent and writes the files you need in your workspace—almost like having two engineers working on the same project simultaneously.\n\nThat’s what `Co` does. With `Co`, the workflow becomes:\n\n1. In File A, reference the function I want from File B.\n2. Save the file.\n3. If necessary, modify File B.\n\n`Co` will automatically generate the module you need and create an appropriate interface based on how you use the function in File A.\n\nThe advantage of this approach is that you don’t need to describe what you want in natural language. Describing a feature in natural language can be more cumbersome than just writing a piece of code to demonstrate it—LLMs seem to work the same way. Using natural language forces us to translate abstract code concepts into descriptive sentences, which every software engineer knows can be frustrating.\n\nThis method may aligns more closely with how LLMs excel at autocomplete.\n\nOf course, this isn’t meant to replace Copilot. Copilot's autocomplete is great, and its ability to generate documentation or refactor code is also useful. `Co` simply complements Copilot by addressing one of its limitations (in my opinion).\n\n### How Does Co Work?\nFrom an AI perspective, it uses a simple prompt and makes a single request—no agent-based techniques are involved.\n\n```md\nWe have \"source files\" reference a file not been written, I need you write the \"referenced file\" contents which fulfill the usage requirements in other source files. You must only return file content without any word.\n\n${sourceFileContents}\n\n---referenced file---\nfilename: ${this.path}\ncontent:\n\n```\n\n### Use Cases and Potential of Co\n\n#### Prototyping\n`Co` is great for quickly generating module interfaces while keeping you in your workflow. Of course, the generated code won’t be perfect—it will still require some manual refinement. An ideal workflow might look like this:\n\n```md\n\u003e Edit Module A  \n\u003e Import module B in A and use it as if it’s already implemented.  \n\u003e Complete Module A.  \n\u003e Edit Module B.  \n\u003e Import module C in B and use it as if it’s already implemented.  \n\u003e Complete Module B.  \n\u003e Edit Module C.  \n\u003e ....  \n```\n\n#### TDD (Test-Driven Development)\nThis workflow is actually quite similar to **TDD**: define how something should be used before implementing it.\n\nWith `Co`, you can generate interface modules while writing test cases. When combined with `Copilot`, this approach can be even more powerful.\n\n\n## Additional: `aicss` (Experimental)\n\u003e [!INFO]\n\u003e This is an implementation of [`ai-css-concept`](https://github.com/shunnNet/ai-css-concept). The functionality is not yet stable and is for demonstration purposes only.\n\n`Co` supports AI-generated CSS. To enable it, set `aicss: true` in `co.config` \n\n```ts\n// co.config.ts\nimport { OpenAITextGenerator, defineCoConfig } from '@imaginary-ai/core'\n\nexport default defineCoConfig({\n  // ...\n  aicss: true\n})\n```\n\nThe method is as follows:\n\n```html\n\u003cdiv class=\"@ai:putChildrenCenterCenter @ai:beautifulBg\"\u003e\n  \u003cp\u003eHello world\u003c/p\u003e\n\u003c/div\u003e\n```\n\nDuring generation, the AI will replace class names with new ones and append the corresponding style rules in `./src/ai.css`.\n\n```html\n\u003cdiv class=\"putChildrenCenterCenter beautifulBg\"\u003e\n  \u003cp\u003eHello world\u003c/p\u003e\n\u003c/div\u003e\n```\n\n```css\n/* ./src/ai.css */\n.putChildrenCenterCenter {\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  height: 100%;\n}\n.beautifulBg {\n  background-color: #f0f0f0;\n  border-radius: 8px;\n  padding: 20px;\n}\n```\n\nIf you don't want to add `@ai:` prefix every class name, you can just `@aicss-all` in the file, then all class name in the file will be generated.\n\n```html\n\u003c!-- @aicss-all --\u003e\n\u003cdiv class=\"putChildrenCenterCenter beautifulBg\"\u003e\n  \u003cp\u003eHello world\u003c/p\u003e\n\u003c/div\u003e\n```\n\nYou can add class name prefix using `@aicss-scope: name`\n\n```html\n\u003c!-- @aicss-all --\u003e\n\u003c!-- @aicss-scope: card --\u003e\n\u003cdiv class=\"putChildrenCenterCenter beautifulBg\"\u003e\n  \u003cp\u003eHello world\u003c/p\u003e\n\u003c/div\u003e\n```\n\nWill generate something like:\n\n```css\n/* ./src/ai.css */\n.card-putChildrenCenterCenter {\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  height: 100%;\n}\n.card-beautifulBg {\n  background-color: #f0f0f0;\n  border-radius: 8px;\n  padding: 20px;\n}\n```\n\n## License\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshunnnet%2Fco","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshunnnet%2Fco","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshunnnet%2Fco/lists"}