Codync
免費、開源的 1:1 替代方案,取代 Grok Bot 與 Muse。從 iPhone、Mac 或 Linux 桌面將 Claude Code、Codex、Cursor 與 40+ 程式碼代理人作為持續機器人傳訊。群組聊天、主題串…
AI 翻譯
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Fa is a programming language designed for both AI agents and humans.
Agents get a language they can't get wrong without the compiler noticing: strict types, typed errors, requirements and mutations, clear diagnostics and an unambiguous grammar. Humans get code that reads almost like natural language, and that runs everywhere: web, server, native, WebAssembly.
Syntax-wise, Fa sits between Rust and TypeScript.
-- Load the score of the current user.
function loadScore = (): Integer throws ApiError requires session: Session => {
let response = try fetchScore(session.user.id)
response.score
}
Fa is in active development. Expect breaking changes.
Like Rust, Fa has no escape hatch: no any, no unchecked casts, no null surprises. If it compiles, it works.
An agent can rely on the compiler as its feedback loop instead of on runtime testing.
Fa brings the ideas of the Effect TypeScript library directly into the language, with no wrappers, generators or pipes to learn. Every function signature tells you everything it can do:
throws): there are no exceptions. Errors are values declared in the signature, and the compiler makes sure each one is either propagated with try or handled with catch.requires): dependencies are passed implicitly through the call stack, but they are part of the signature. Calling a function without providing what it requires is a compile error.mutates, invalidates): a function declares what it modifies, down to a field or an element, and which references it can invalidate.type ApiError = Errors {
NetworkError = { message: String }
TimeoutError = { duration: Integer }
}
type Session = {
user: { id: String, name: String }
}
function greet = () requires session: Session => {
console.log("Hello, {session.user.name}!")
}
function main = () throws ApiError => {
provide Session = { user = { id = "42", name = "Ada" } }
greet() -- the session is provided implicitly
-- `try` propagates the error if the call fails
let score = try loadScore()
-- `catch` handles it
let scoreOrZero = loadScore() catch error => 0
}
Diagnostics explain what went wrong, where, and how to fix it. They are written to be acted upon by a human or an agent without guesswork.
Every construct has a single meaning and, as much as possible, a single way to be written. There are few keywords, no context-dependent parsing and no hidden rules, which makes Fa easy to read and easy to generate.
Documentation is part of the language, not a convention on top of it. A comment written right above a declaration is its documentation: it is attached to the declaration and are available to the compiler, the language server and the tooling, so agents always find the documentation right next to the code they work on.
Fa favors words and simple operators over symbols. Code should read almost like a sentence:
for person in persons {
if person.age is 18 {
console.log("Welcome to adulthood, {person.name}!")
}
}
Fa is a universal language: write your code once, then compile it to JavaScript (browser, Bun, Node.js, Deno), native, WebAssembly or Rust source code.
The same code base can power your tooling, your applications and your games.
Fa has no garbage collector and no borrow checker, yet it is 100% memory-safe. It relies on two concepts.
When you reference an element of a collection, its type says where it is stored. The compiler tracks the operations that can move or remove elements, as precisely as it can: after one of them, the references it may have broken must be declared again before being used.
mutable persons: Array(Person) = [{ name = "Ana" }, { name = "Bao" }, { name = "Cleo" }]
use someone = persons[1] -- type: `Person in persons`
someone.name = "John" -- fine: modifying an element keeps the references valid
persons.pop() -- fine: `pop` only invalidates the last element
persons.push({ name = "Dan" }) -- `push` may reallocate the array: every reference into `persons` is invalidated
console.log(someone.name) -- error: `someone` was invalidated by `persons.push`: declare it again with `use someone = persons[...]`
A field that references another object names the collection it lives in, and is one side of a relation whose other side is declared too. The compiler keeps both sides in sync, and deleting an object cleans up every relation it was part of, so no reference is ever left dangling.
mutable people: Bag(Person) = []
type Person = {
name: String
bestFriend: (Person in people)?
bestFriendOf: Bag(people->bestFriend) -- the people whose `bestFriend` is me
}
use ana = people.add({ name = "Ana" })
use bao = people.add({ name = "Bao" })
ana.bestFriend = bao -- `bao.bestFriendOf` is updated automatically
people.delete(bao) -- `ana.bestFriend` becomes `none`
The full documentation lives in documentation/ and is published by the website in packages/website.
To test Fa locally, you need Rust installed. Install it with rustup from https://rustup.rs.
The parser project lives in packages/parser and builds as the fa-parser crate.
From the repository root:
cargo build -p fa-parser
The parser binary expects a file path and prints the parsed tree.
cargo run -p fa-parser -- path/to/file.fa
console.log("Hello, world")