@ganju/cli

中文文档
0.0.26发布于 2026/11/13Apache-2.0ES Module近 30 天下载 2743

从终端写入、部署并调试 Ganju 自定义工具

中文使用文档
文档目录17 节
  1. 图标
  2. ganju data
  3. 数据库
  4. 表格和栏
  5. 行数
  6. 命名的查询
  7. 作为代码的Schema : ganju.data.json
  8. 破坏命令
  9. ganju.json
  10. 两个写路由器的方法
  11. 那栋楼做什么
  12. 源头 除了捆绑
  13. 替换应用程序中的代码
  14. 工具内插
  15. 环境
  16. 签名于
  17. 从这回购开始建造

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|revokeCI 的个人访问令牌, 范围为链接项目
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)access read, (中文(简体) ), history 没错, onDelete restrict,第一个文本栏为 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_VALUEganju 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 保持一个真正的依赖性,因为它运送一个特定平台的二进制 无法捆绑.

版本与发布记录

@ganju/cli 共发布 24 个版本,首次发布于 2026/08/29;过去 12 个月发布了 24 个版本。

版本发布日期距今
0.0.26latest2026/11/133 天前
0.0.252026/11/114 天前
0.0.242026/11/115 天前
0.0.232026/11/106 天前
0.0.212026/11/079 天前
0.0.202026/11/079 天前

关于 @ganju/cli 的常见问题

@ganju/cli 是什么?

从终端写入、部署并调试 Ganju 自定义工具

如何安装 @ganju/cli?

在项目目录运行 npm install @ganju/cli,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 ganju,可以用 npx ganju 直接运行。

@ganju/cli 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/ganju__cli 是否存在。

@ganju/cli 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@ganju/cli 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@ganju/cli 可以商用吗?

@ganju/cli 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@ganju/cli 的下载量有多少?

根据 npm 官方下载统计,@ganju/cli 在 2026/10/16 – 2026/11/14 这 30 天内被下载 2,743 次,日均约 91 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@ganju/cli 还在维护吗?

最新版本 0.0.26 发布于 2026/11/13(3 天前);至今共发布 24 个版本,其中过去 12 个月发布了 24 个;首次发布于 2026/08/29。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。