LLeMbas CLI 1.0.0
ci / check (push) Waiting to run

The first public release of LLeMbas CLI: a terminal coding agent and project manager for any LLM
API, with permission modes, git snapshots, memory and skills, knowledge bases, MCP, voice, and a
link to a LLeMbas instance whose web UI can work its sessions too. Signed Linux binaries for x64
and arm64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
HomerandClaude Opus 5.5 committed 2026-10-09 21:59:03 +00:00
commit f9bad01ed7
355 files changed
+47028

No files matched your search

+90
View File
@@ -0,0 +1,90 @@
import { describe, expect, test } from "bun:test"
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs"
import { tmpdir } from "node:os"
import { join } from "node:path"
import { paths } from "../src/config/paths.ts"
import { hardlineRules } from "../src/permission/hardline.ts"
import { attachmentsFor } from "../src/project/attach.ts"
import { customCommands, expandCommand } from "../src/project/commands.ts"
import { FileIndex } from "../src/project/files.ts"
import { findProject, projectDirName } from "../src/project/root.ts"
function tree() {
const root = mkdtempSync(join(tmpdir(), "ph-proj-"))
mkdirSync(join(root, "src/deep"), { recursive: true })
writeFileSync(join(root, "src/app.ts"), Array.from({ length: 30 }, (_, i) => `line ${i + 1}`).join("\n") + "\n")
writeFileSync(join(root, "src/deep/util.ts"), "export {}\n")
writeFileSync(join(root, "README.md"), "# hi\n")
return root
}
describe("@ attachments", () => {
test("a file, a line range, a directory; an email is left alone; attached files count as read", () => {
const root = tree()
const ctx = { root, cwd: root, readFiles: new Set<string>(), fileStamps: new Map() }
const atts = attachmentsFor("look at @src/app.ts and @src/app.ts#3-5 and @src/ — mail me@example.com", ctx)
expect(atts.map((a) => a.path)).toEqual(["src/app.ts", "src/app.ts", "src/"])
expect(atts[0]!.text).toStartWith('<file path="src/app.ts">\n1: line 1')
expect(atts[1]!.text).toBe('<file path="src/app.ts" lines="3-5">\n3: line 3\n4: line 4\n5: line 5\n</file>')
expect(atts[2]!.text).toBe('<directory path="src/">\napp.ts\ndeep/\n</directory>')
expect(ctx.readFiles.has(join(root, "src/app.ts"))).toBe(true)
})
})
describe("custom commands", () => {
test("global and project, the project overriding; $ARGUMENTS, $1, !`cmd`, and the hardline", () => {
const root = tree()
mkdirSync(join(paths.config, "commands"), { recursive: true })
writeFileSync(join(paths.config, "commands", "review.md"), "---\ndescription: review a file\n---\nReview $1 carefully. All: $ARGUMENTS\nBranch: !`echo main`\n")
writeFileSync(join(paths.config, "commands", "danger.md"), "Here: !`rm -rf /`\n")
const pdir = join(root, ".agent")
mkdirSync(join(pdir, "commands"), { recursive: true })
writeFileSync(join(pdir, "commands", "danger.md"), "---\ndescription: project one\n---\nsafe\n")
const cmds = customCommands(pdir)
const review = cmds.find((c) => c.name === "review")!
expect(review.description).toBe("review a file")
expect(cmds.find((c) => c.name === "danger")!.source).toBe("project")
expect(expandCommand(review, "src/app.ts quickly", root, hardlineRules())).toBe("Review src/app.ts carefully. All: src/app.ts quickly\nBranch: main")
const globalDanger = customCommands(undefined).find((c) => c.name === "danger")!
expect(expandCommand(globalDanger, "", root, hardlineRules())).toContain("[not run — recursive delete of the root filesystem]")
})
})
describe("file index", () => {
test("fuzzy match, and a trailing / lists one level", () => {
const idx = new FileIndex(tree())
expect(idx.search("utl")[0]).toBe("src/deep/util.ts")
expect(idx.search("src/")).toEqual(["src/deep/", "src/app.ts"])
})
})
describe("the project directory", () => {
test("a new project gets .agent at the git root; an empty .agent is where it goes", () => {
const root = mkdtempSync(join(tmpdir(), "lembas-proj-"))
mkdirSync(join(root, ".git"))
mkdirSync(join(root, "src"))
expect(findProject(join(root, "src"))).toMatchObject({ root, dir: join(root, ".agent"), exists: false })
mkdirSync(join(root, ".agent"))
expect(projectDirName(root)).toBe(".agent")
})
test("another tool's .agent is not a project: a new one is .lembas, not inside it", () => {
const theirs = mkdtempSync(join(tmpdir(), "lembas-proj-"))
mkdirSync(join(theirs, ".git"))
mkdirSync(join(theirs, ".agent", "rules"), { recursive: true })
expect(findProject(theirs)).toMatchObject({ root: theirs, dir: join(theirs, ".lembas"), exists: false })
mkdirSync(join(theirs, ".lembas"))
expect(findProject(theirs)).toMatchObject({ dir: join(theirs, ".lembas"), exists: true })
})
test("our own .agent is found by any one of its markers", () => {
for (const marker of ["config.yaml", "plans", "tasks.md", "local"]) {
const mine = mkdtempSync(join(tmpdir(), "lembas-proj-"))
if (marker.includes(".")) {
mkdirSync(join(mine, ".agent"))
writeFileSync(join(mine, ".agent", marker), "")
} else mkdirSync(join(mine, ".agent", marker), { recursive: true })
expect(findProject(mine)).toMatchObject({ dir: join(mine, ".agent"), exists: true })
}
})
})