ganju - 国家行动倡议
从终端写入、部署并调试自定义工具,并管理工程的 数据库。 这里的一切都是薄的 端点的客户端已经使用; 它中没有任何是第二个写入 路径.
npm install -g @ganju/cli
ganju init my-tools
cd my-tools
ganju login
ganju link
ganju deploy
{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}从盒子里出来 {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}这话要说 https://api.ganju.ai,所以新安装需要
没有配置 。 指别的地方——你自己的例子,或者当地API——
与 GANJU_API_URL。 。 。 .
图标
| 命令 | 它会做什么 |
|---|---|
ganju init [dir] | 脚手架a ganju.json 和部署在现场的操作员 |
ganju login 编号 : logout 编号 : whoami | 签到这台机器,然后离开 |
ganju link | 点 ganju.json 在一个组织和项目中,如果没有,则创建文件(--status 读它) |
ganju build | 打开工具, 编译并修改、 写入 .ganju/bundle.js报告大小. --strict 提示失败 |
ganju deploy | 构建、上传和发布( E)--draft 在出版前停下来, --force 替换应用程序中制作的活版) |
ganju test <tool> | 在不发布的情况下对一个样本输入运行一个工具 |
ganju logs | 最近打来的电话 ctx.log 产出(--follow 继续看) |
ganju versions 编号 : ganju rollback <n> | 什么存在,哪个是活的,然后回去 |
ganju secret set|list|rm | 价值 ctx.secret() 读取 |
ganju token create|list|revoke | CI 的个人访问令牌, 范围为链接项目 |
ganju data … | 该项目的数据库:表格、行、导入、导出、恢复和计划作为代码—— 下级 |
ganju data
项目数据库(Pro and Entertainment),从终端. 每个命令
呼唤 数据 API 路由仪表板使用,
项目 ganju.json 链接到 (ganju link 在空文件夹中
一个,没有 ganju init 因此,此处的文字由
相同的规则和记录方式: ganju login, (中文(简体) ),
或作为 cli:<token id> 与 GANJU_API_TOKEN 设置为个人访问符.
A 类 429 {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}而不是失败 {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}我从一个符号的每分钟限数里
长导入半径.
数据库
| 命令 | 它会做什么 |
|---|---|
ganju data create [--name <name>] | 制作数据库. --replace --yes 开始的时候,删除的仍然可以恢复,放弃它 |
ganju data info | 现状、规模、表格和表格副本 |
ganju data index add|dismiss <id> | 就指数建议采取行动. info 列出它们, 并附上它们的ID: 甘珠建议索引一个列, 在读取比它们返回的多很多行时, 经常过滤查询。 它还在写给很多的表格上标出一个在30天内没有使用的索引查询;没有删除任何信息 |
ganju data drop --yes --confirm <name> | 删去,可以休息七天 |
ganju data restore | 撤消删除 |
ganju data restore --at <ISO time> --yes | 把所有东西都放回原样(30天内). 时间需要抵消: 2026-10-30T09:15:00-05:00 或者说 …Z |
ganju data restore --bookmark <b> --yes | 全部放回书签上: 一滴一滴, 类型更改, 导入 --replace 或印出检查站 |
ganju data checkpoint | 现在的书签, 独自在Stdout: B=$(ganju data checkpoint) |
ganju data time-zone [<zone>] [--clear] | 区约会时间回 助理,职能和任何人 谁不发送,例如. America/Bogota没有区域,就打印出来 |
ganju data export [--format jsonl|csv] [--out <dir>] | schema.json 和每个表格的一个文件,下载到文件夹中 |
ganju data changes | 计划更改日志:谁改变了什么,何时 |
ganju data copy [status|wait|dismiss] | 表格上超过10万行的字型变化会在背景中复制; 跟着它, 或者清除一个失败的 |
表格和栏
| 命令 | 它会做什么 |
|---|---|
ganju data tables | 每张表格及其栏目 |
ganju data table create <name> --schema <file> | 文件持有 { "columns": [...] },或 ganju.data.json (使用该名称的表格) |
ganju data table rename <name> <new-name> | |
ganju data table rm <name> --yes --confirm <name> | 放下枪 打印带回来的书签 |
ganju data column add <table> <name> <type> [--input '<json>'] | --input 持有其余: '{"required":true,"min":0}', (中文(简体) ), '{"table":"menu","onDelete":"cascade"}' |
ganju data column rename <table> <name> <new-name> | 保留每个值 |
ganju data column change <table> <name> --input '<json>' | 任何设置。 一个新的 type 或关系 table 复制表格和需要 --yes |
ganju data column rm <table> <name> --yes | 放下枪 打印带回来的书签 |
复制大表格的更改等待复制并显示其进展;
--no-wait 把终端拿回来,然后 ganju data copy wait 捡起.
当它运行时,表格拒绝其他更改并写到它.
行数
| 命令 | 它会做什么 |
|---|---|
ganju data rows <table> | 一行一页. --where, (中文(简体) ), --sort -price,name, (中文(简体) ), --search <text>, (中文(简体) ), --limit (最多500个), --cursor, (中文(简体) ), --include <relation columns>, (中文(简体) ), --all 每页, --json |
ganju data get <table> <id> | 一行,还有它 version |
ganju data insert <table> --input '<json>' | --input-file rows.jsonl | 一行,JSON列表或JSONL文件. 最多五千行是一行的,要么全写,要么全写,要么全写,要么全不写 |
ganju data update <table> <id> --input '<json>' [--version <n>] | 数值,或相对变化: '{"stock":{"decrement":2}}'与 --version,一行更改后被拒绝,显示谁改变了,现在如何 |
ganju data delete <table> <id>... [--yes] | 显示级联会先移除什么, 当限制时拒绝。 多个 ids 一起删除或根本不删除 |
ganju data history <table> <id> | 过去90天的每一个变化,是谁做的 |
ganju data write --input-file ops.json | 多个表格插入、更新和删除,全部或无({ "$ref": <step> } 用于较早插入的 id) |
ganju data import <table> <file> | A 类 .csv, (中文(简体) ), .tsv, (中文(简体) ), .json 或者说 .jsonl 文档,分批500份 |
命名的查询
A 类 SELECT 以命名参数保存一次( e):from),用于报告行
过滤器无法表达. 保存时选中它: 一个声明, 只读
这个数据库的表格。 函数运行它 ctx.data.run; 与
"assistant": true 频道bots也可以运行它.
| 命令 | 它会做什么 |
|---|---|
ganju data queries | 保存的查询、其参数和所读表格 |
ganju data query save --input-file sales.json | { "name", "description", "sql", "params": [{ "name": "from", "type": "datetime" }], "assistant" }。保存现有名称取而代之 |
ganju data query rm <name> --yes | 删除它 |
ganju data run <name> [--input '{"from":"2026-10-01T00:00:00-05:00"}'] [--limit 100] [--json] | 它的行数,最多500行 |
--where 每个旗帜都有一个条件,每个旗帜必须持有:
| 您输入 | API获得 |
|---|---|
--where status=open | {"status":"open"} |
--where 'price<30000' (另见: <= > >= !=(中文(简体) ) | {"price":{"lt":30000}} |
--where 'name~pizza' 编号 : --where 'name^=Marg' | {"name":{"contains":"pizza"}} 编号 : {"name":{"startsWith":"Marg"}} |
--where 'status=[open,done]' 编号 : --where 'id!=[1,2]' | {"status":{"in":["open","done"]}} 编号 : {"id":{"notIn":[1,2]}} |
--where note=null 编号 : --where note!=null | {"note":null} 编号 : {"note":{"ne":null}} |
--where phone=3001234567 | {"phone":"3001234567"} ——在文本一栏中,数值为已键入文本 |
--where 'code="007"' | {"code":"007"} ——引文在任意一栏中保留一个值作为文本 |
--where 'price>=10' --where 'price<20' | {"price":{"gte":10,"lt":20}} |
--where 'product.name=Margherita' | 表格中的一列关系点 |
--where '{"price":{"lt":30000}}' | jSON本身,就像 |
文本、长文本、电话、电子邮件、 URL、 enum、 日期或日期时间列、 a
值为已键入的文本(只有) null 意思是空的),从表格读取
列类型,通过关系。 其他列,数字, true, (中文(简体) ), false
财务报告和审定财务报表 null 意思是自己,其他东西都是文字。 Raw JSON 作为
写作.
引用你壳壳的完整条件 <, (中文(简体) ), > 或空间.
import 使用相同的代码:
按名称或标签与列相匹配(大小写、口音和标出),
--map 'Precio (COP)=price' 逐个点数--map 'Notes=' 离开它
数字如 28.000 财务报告和审定财务报表 1.234,5 与他们的数千人一起阅读
分离器--decimal-mark . | , 当文件模糊不清时),和关系
列与其它表格的显示值相匹配,因此“Margherita”成为其
排的身份证。 在发送任何信息之前检查每个单元格;批次拒绝
一行被分割,直到找到, 所以它只花费自己。 这些行
拒绝,为什么,写给 <file>.refused.csv (或 --out),准备
修复并再次导入.
--replace 将表格的每行换回文件。 这需要 --yes 财务报告和审定财务报表
--confirm <table>,显示其它位置的行(并停止)
如果限制会挡住它,则先取一个检查站,打印
撤销的书签。 两边最多有五千行,只有一行:
老一行只有每个新一行着陆 当写字被拒绝时,行
在它的后面发现有从未犯罪过的试字
整个文件写入 <file>.marked.csv 每一个问题,除了它的
行; 表中没有任何变化 .
电子表格( E).xlsx, (中文(简体) ), .xls, (中文(简体) ), .ods直接读取:其第一个工作表,或
一个 --sheet <name> 名称。 空行被跳过,日期作为
日期.
作为代码的Schema : ganju.data.json
ganju data schema pull # write the database's schema to ganju.data.json
ganju data schema diff # what push would change
ganju data schema push # apply it
文件为 { "tables": [...] },每个表格写的方式,你会打它
来创建它——与导出形状相同 schema.json,所以无论工作
与 --schema <file>。 。 。 . pull 之后 push 给回同样的文件,所以它
diff in a pull request is a change to the schema and nothing else. 在拉力请求中, diff in a puff request 是一种对策略的改变, 没有什么别的.
push 数据库的更改日志中还指出,其表格来自
文档。 仪表板的助手然后警告说,一个表格或一栏的更改
下个会放回去的 push。 。 。 .
diff 匹配表格和列 按名称数字 :
+ create table orders (customer, status)
+ add column menu.notes long_text
~ change table menu: label "Menu"
~ change menu.stock: default 5 (copies the table)
- change menu.price: type "decimal" (copies the table) (needs --yes)
- drop column menu.code (needs --yes)
- drop table promos (needs --yes)
- 命名的查询进入
"queries": [...],每个ganju data query save取下它, 并按名字排序 :+ save query sales_by_dish (:from, :to)。 。 。 .pull当数据库有时,就写。 没有文件queries保留数据库的查询; 与此相关, 缺少一个查询 文件被删除, 需要--yes。 。 。 . - 文件被忽略的密钥表示它们的默认值( E)
accessread, (中文(简体) ),history没错,onDeleterestrict,第一个文本栏为displayColumn因此,一个 手写文件短而取出的文件相等. - 新建表格的顺序, 每个关系的目标都存在 先说 创建两个相互对应的新表格 栏,一旦两者存在,就添加该栏.
- 丢弃的表格按 API 接受的顺序进行: 它拒绝丢弃表格 而其他的点。 每个点的表格一起下降 其他则先失去一个关系栏,这样可以释放其余部分.
push应用新表格、新列和已更改的设置. 投放和类型变化 (包括将关系指到另一个表格) 仅与--yes,在一个书签的检查站之后 解除他们。 无--yes在脚本中,按下其余部分并退出 1 点出它遗漏的东西; 在终端里它会问.- 重命名的表格或一栏读作下放并添加,其中
--yes将 应用方式为清空旧的。 重命名为ganju data table rename或者说ganju data column rename,则pull。 。 。 .
破坏命令
任何需要删除、删除或重写的数据 --yes; 丢弃
数据库或表格,以及 import --replace,也需要输入的名称
--confirm。在终点站需要一面失踪的旗帜。 没有一个人——CI, a
管子——命令拒绝并改变一无所有,而不是等待一个快取.
ganju.json
{
"artifact": "acme-support",
"organizationId": "…", // written by `ganju link`
"projectId": "…",
// Row-level, because that is the level they are enforced at: one script per
// artifact, one set of rules for all of it. They travel with the deploy.
"connections": ["google-gmail"],
"allowedHosts": ["api.acme.com"],
"timeoutMs": 10000,
"resourceAccess": "own",
// Upload this folder's readable source beside the bundle (default true).
"uploadSource": true,
"tools": [
{
"name": "lookup-order",
"title": "Look up order",
"description": "Find an order by its id. Use when the customer gives an order number.",
"entry": "src/lookupOrder.js",
"input": {
"type": "object",
"properties": { "orderId": { "type": "string" } },
"required": ["orderId"]
},
"output": { "type": "object", "properties": { "status": { "type": "string" } } },
"annotations": { "readOnlyHint": true }
}
]
}
annotations 这是 MCP 工具说明, (中文(简体) ),
带有 spec 名称 : readOnlyHint, (中文(简体) ), destructiveHint, (中文(简体) ), idempotentHint, (中文(简体) ),
openWorldHint。它们能传送到 MCP 客户端作为提示,它们决定频道是什么
bot确认组织何时启动 确认敏感行动(单位:千美元)
无法声明的工具 readOnlyHint: true 也没有 destructiveHint: false 实值
问起它运行之前。 标记只读的外观; 留下任何发送,
收费或删除无标记.
档案里没有秘密 绝对没有. ctx.secret('ACME_KEY')
在电话时间通过经纪人解决身份证明问题 所以秘密是一回事
您发送一次而不是一个值 承诺在您的源。 使用
ganju secret set它从下一个呼叫开始直播,之后没有部署.
两个写路由器的方法
给每个工具一个 entry 路由是从舱中产生
工具名称完全写在一个地方,以及 lookup-order 对
lookupOrder 不再成为可能发生的事情:
// src/lookupOrder.js
import { defineTool } from '@ganju/sdk';
export default defineTool(async (input, ctx) => {
const { accessToken } = await ctx.connection('google-gmail');
return { status: 'shipped' };
});
或者给 无 其中之一,然后自己写地图, 在文件命名
main (默认) src/index.ts:
import { createHandler, defineTool } from '@ganju/sdk';
export default createHandler({
'lookup-order': defineTool(async (input, ctx) => ({ status: 'shipped' }))
});
由于这两项决议都遭到拒绝而不是解决 默地放下了作者所写的一半.
那栋楼做什么
esbuild,捆绑在一个ES模块上——这不是优化而是步骤
因为一个已部署的脚本是一个
单单元。 TypeScript 工作; 类型被剥离, 从未检查, 所以运行 tsc
如果你想要强制他们的话.
@ganju/sdk 实值 没有 捆绑了 重写为 ./ganju-sdk.js,兄弟们
模块,发布管道附着在每次上传中——所以在
捆绑会是死体重, 和一个版本冷冻到它会从
帮它说话.
上传是 bundle,这意味着仪表盘的编辑器显示它只读
而不是邀请某人 覆盖一个真正的建筑与内容
文本框中输入的。 使用仪表板进行代码, 您想在那里编辑 .
源头 除了捆绑
ganju deploy 上传工程的可读源, 所以仪表板
显示您的真实文件( 仅读) , 而不是已修改的捆绑 。 只不过
显示; 捆绑是运行的 .
- 哪些文件 : 意味着跟踪文件加上未跟踪文件
你们的
.gitignore这并不排斥。 在Git仓库外.gitignore项目中的文件直接被读取. - 从未上传 :
node_modules, (中文(简体) ),.ganju, (中文(简体) ),.git, (中文(简体) ),.env*,锁文件 (单位:千美元)package-lock.json, (中文(简体) ),yarn.lock, (中文(简体) ),pnpm-lock.yaml, (中文(简体) ),bun.lock[b]二进制 文档. - 大小 : 超过256 KB的文件被单独忽略。 超过 2 MB (或 500个文件)上传到没有任何来源,说到此,反正部署.
- 关机: 设定
"uploadSource": false内ganju.json。 。 。 .
替换应用程序中的代码
一个部署将这个文件夹作为整个项目发布。 如果现场版本是
(由助理或仪表板编辑), ganju deploy 先说,然后列出
函数将停止工作。 在终点站,它问 之前继续
脚本停止,除非你通过 --forceA级 --draft 部署不取代任何东西,
所以它没有检查.
工具内插
ganju build 检查每个工具是如何在 ganju.json 以模特儿盟誓
关于:
- 缺少或非常简短的描述,或从未说明何时使用 工具;
- 没有
annotations- 然后,工具被视作一个可能改变事物的工具, 当组织确认敏感时 行动; - 没有描述的输入属性;
- 两个在名字或描述上相像的工具.
警告不会停止建设,除非你通过 --strict这是给中情局的.
ganju deploy 打印与 API 运行的相同的检查, API 也查看
服务器的其他工具—— 与它们重叠, 太多启用的工具出现
在这里.
环境
| 变量 | 对于 |
|---|---|
GANJU_API_URL | 哪个部门要跟谁说话? 每个项目的固定表如下: apiUrl 内 ganju.json |
GANJU_API_TOKEN | 一个没有浏览器的机器(CI,一个容器,SSH)的访问符. 绕过存储的登录 . ganju token create 薄荷 耐用 |
GANJU_SECRET_VALUE | ganju secret set NAME 从这里读取值, 让它远离外壳历史 |
GANJU_CONFIG_DIR | 代币店住的地方. 默认 ~/.ganju |
签名于
ganju login 是对同一授权进行回转(RFC 8252)
服务器 MCP 客户端使用: CLI 持有端口打开,将您的浏览器发送到
授权端点, 并读取代码 从方向。 客户是公众 -
没有秘密, PKCE, 因为用 npm 包运来的秘密是一个秘密
软件包的每个用户都有 它通过RFC 7591动态进行自我注册
在第一个登录时进行注册,所以不需要手工提供.
托肯斯住在这里 ~/.ganju/credentials.json模式 0600,由 API 来源键入 -
因此,反对当地API和同时反对生产不是
每次你碰另一只时,就把你从其中记录下来.
从这回购开始建造
npm run build -w @ganju/cli 类型检查 tsc 然后捆绑在一起
建立为单身 dist/index.js。 。 。 .
它捆绑而不是宣布 @ganju/utils 作为依赖,尽管
软件包已经发布:全球安装的 CLI 不应拖动 zod, dayjs
和密码套房在某人的机器上读取8个常数和3个
在锁步中释放的软件包不应对每个软件包进行半解析
其他费用。 这8个价值观存在于 @ganju/utils/cliConstants,模块
输入主常数模块将包含整个
对象字形,因为捆绑者不能摇起一棵树. ganju data 携带
@ganju/utils/dataImport 及其所需的模块,所以每个导入检查
带有数据库本身规则的单元格,但不为 Zod: Data API 路由列表
仅输入其类型,复制的CLI呼叫由
tsc。 。 。 .
npm test -w @ganju/cli 运行单元测试(node:test: --where
简写, schema diff 及其订单, 以及 CSV 读取器.
esbuild 保持一个真正的依赖性,因为它运送一个特定平台的二进制
无法捆绑.