triss-coworker

mcp
Guvenlik Denetimi
Basarisiz
Health Uyari
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Basarisiz
  • fs module — File system access in .github/workflows/bundle-checks.yml
  • child_process — Shell command execution capability in .github/workflows/publish.yml
  • execSync — Synchronous shell command execution in .github/workflows/publish.yml
  • exec() — Shell command execution in .github/workflows/publish.yml
  • process.env — Environment variable access in .github/workflows/publish.yml
  • fs module — File system access in .github/workflows/publish.yml
  • network request — Outbound network request in .github/workflows/publish.yml
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

Cheap DeepSeek coworker for Claude Code/Codex. Delegate bulk reads, boilerplate, and chat extraction to save 60-70% of your token budget.

README.md

Triss Coworker

A cheap DeepSeek-backed coworker for your AI coding agent.
Delegate bulk reads, boilerplate generation, and chat extraction.
Save 60–70% of your token budget. Pay cents, not dollars.

npm version
npm downloads
Tests
Node.js
License: MIT
Changelog

Triss is a small CLI (triss) that hands token-heavy I/O off to a cheap
DeepSeek model so your expensive primary agent (Claude Code, Codex, or
anything else that can run a shell/MCP tool) stays focused on reasoning and
edits.

Triss is the helpful sorceress on your team.
Strictly fewer portals, substantially more git diff.

It also ships with first-class integrations for Jira, Confluence, Linear,
GitHub Issues, and GitLab Issues, so your agent can search, read, create,
update, comment on, and transition work items without pulling thousands of
tokens of tracker chatter into its own context. Adding a new provider
(Notion, Asana, Sentry, ...) takes one folder — see
extension guide.


Contents

Requirements

  • Node.js ≥ 22.12 (LTS). Check with node --version.
    • Don't have it? Install via nvm, fnm, Homebrew (brew install node), or nodejs.org.
  • npm (ships with Node.js) — used only for the package-manager install path.
    pnpm and yarn also work.
  • The standalone bash installer and update discovery do not require npm, pnpm,
    yarn, git, tar, unzip, or a checksum utility once a standalone Release exists.
  • A DeepSeek API key (free tier works) for the worker model: https://platform.deepseek.com/.

No external service or system-wide binary is required for the core CLI. npm
dependencies are installed with the package.

Install

Option A — npm / pnpm / yarn (recommended)

npm install -g triss-coworker
# or
pnpm add -g triss-coworker
# or
yarn global add triss-coworker

Published on npm as
triss-coworker; the CLI
binary is triss.

Prefer no global install? npx triss-coworker <subcommand> (or
pnpm dlx triss-coworker <subcommand>) works — e.g.
npx triss-coworker ask --paths src/ --question "…". Triss is meant
to live alongside your agent, though, so a global install is usually
less friction day-to-day.

Option B — one-line bash installer

curl -fsSL https://raw.githubusercontent.com/ayleen/triss-coworker/main/install.sh | bash

This installs a receipt-backed standalone copy under
~/.local/share/triss and links ~/.local/bin/triss. Override those paths for
the install command with TRISS_STANDALONE_HOME and TRISS_BIN_DIR.
TRISS_HOME remains reserved for the old git installer and is never interpreted
as standalone write authority. During the first-release transition only, a
verified missing standalone asset may use the previous git+npm path for a fresh
empty legacy target; existing legacy checkouts are never pulled or modified.

Option C — from source

git clone https://github.com/ayleen/triss-coworker.git
cd triss-coworker
npm install   # or: pnpm install / yarn install
npm link      # or: pnpm link --global / yarn link

Then verify:

triss --version
triss --help
triss status

Updates

During successful interactive CLI use, Triss checks a fixed GitHub Release
endpoint at most once per cache window and prints a throttled update notice to
stderr. A due check is awaited and adds at most 1.1 seconds; a fresh cache adds
no network wait. Long-running MCP servers begin the same check only after the
MCP initialization handshake and use MCP logging plus stderr fallback.

triss update                  # fresh status and guidance; no file changes
triss update --json           # one machine-readable object
triss update --apply          # receipt-backed standalone installs only
triss update --rollback       # offline rollback to a verified prior version

Apply and rollback require confirmation; add --yes for non-interactive
operation confirmation. Breaking a proven-stale update lock is a separate
authorization: add --break-lock (and also --yes when non-interactive).
Package-manager, source, ephemeral, legacy-git, and unknown installations remain
read-only and receive installation-specific guidance.

A valid Release that requires a newer Node is reported as available but cannot
be applied until Node is upgraded. Standalone status reports retained version
count and receipt-recorded payload bytes; automatic pruning is not performed.
Set TRISS_UPDATE_CHECK=0 to disable passive checks and notices. Explicit
triss update remains available. A running MCP host must be restarted after an
update to load the new version.

Configure

triss config wizard

The wizard first asks Standard vs Advanced:

  • Standard — for most users. Two prompts for API key + worker model
    (writes the model into both flash and pro so --model pro works), then
    asks which agent to wire up: Claude / Codex / Both. No questions about
    Jira/Linear/base URL/etc. Recommended starting point.
  • Advanced — full control: separate flash/pro presets, custom
    base URL, integrations (Jira, Linear, …), default-preset choice.

Skip the prompt with --standard or --advanced. Add --local to save
into <project>/.triss.env instead of the global file (useful when
different repos use different Jira instances).

Then verify:

triss status

Per-project credentials

Different orgs / Jira instances per project? triss config wizard --local
saves to <project>/.triss.env instead of the global file. Project values
override global values when you cd into that repo. The file is
automatically chmod 600'd and added to .gitignore.

Step-by-step recipes for the common setups (single workspace, multi-Jira
per project, CI, etc.) live in
docs/configuration.md.

Updating one variable

triss config set TRISS_WORKER_API_KEY            # masked prompt → global
triss config set ATLASSIAN_API_TOKEN --local # masked prompt → ./.triss.env
echo "$KEY" | triss config set LINEAR_API_KEY -   # from stdin (CI)

Full reference: docs/configuration.md.

Shell completions

# bash:
echo 'eval "$(triss completion bash)"' >> ~/.bashrc

# zsh:
echo 'eval "$(triss completion zsh)"' >> ~/.zshrc

After re-sourcing your shell profile, triss <Tab> lists all
top-level commands; triss config <Tab>, triss jira <Tab>,
triss linear <Tab> list subcommands.

Connect your agent

Wizard takes care of this for you

Mode in triss config wizard What it does about your agent
Standard (default) After the two prompts, asks Claude / Codex / Both and installs MCP + global rules accordingly.
Advanced (--advanced) Asks at the end: Both / MCP only / rules only / Skip. Default = Both.

The two paths cooperate: MCP is primary, CLAUDE.md / AGENTS.md rules are
the fallback. If MCP fails to load, the rules keep the agent working. If you
don't know what to pick, just use Standard.

Two complementary paths — pick either, both, or neither.

Option 1 — CLAUDE.md rules (lightweight)

cd ~/my-project
triss init                 # asks: Claude / Codex / Both, then writes the rules file(s)
triss init --target claude # writes ./CLAUDE.md without asking
triss init --target codex  # writes ./AGENTS.md for Codex
triss init --target both   # writes both ./CLAUDE.md and ./AGENTS.md
triss init --global        # same prompt, but writes into ~/.claude/ or ~/.codex/

Agent reads the rules and invokes Triss via the shell. No special
setup. Best when you also want the same commands available outside the
agent (in your own scripts, CI, etc).

The block is intentionally tiny (~15 lines): it names the MCP tools,
states when to delegate vs not, and points at triss agent-help for the
full cookbook. The cookbook is rendered on demand — the agent reads it
once when it actually needs the long reference, instead of loading 200
lines of instructions into every session. This keeps the always-on
context cost negligible compared to the savings Triss provides.

Option 2 — MCP server (deeper integration)

triss mcp install                  # asks: Claude / Codex / Both, then Project / Global
triss mcp install --target claude  # Claude only, prompts for scope
triss mcp install --target codex   # ~/.codex/config.toml (always global)
triss mcp install --target both    # both configs (Codex stays global)
triss mcp install --local          # ./.mcp.json in cwd (claude only, skips scope prompt)
triss mcp install --global         # ~/.claude.json (skips scope prompt)

For Claude Code: restart your session — triss appears in claude /mcp
with the per-tool list. For Codex: restart the Codex CLI session;
verify with codex mcp list. Tools become first-class (faster, per-tool
permissions, no Bash subprocess overhead).

The Codex entry includes startup_timeout_sec = 30 and tool_timeout_sec = 5460. The outer tool timeout must exceed 3 × the selected per-attempt
timeout plus headroom, because the OpenAI SDK keeps its retries enabled
(2 retries, 3 attempts total) and each attempt may run the full internal
timeout: the default 5460s covers only the default 1800s-per-attempt GLM
review (3 × 1800s + 60s), so a long thinking review is never killed by
the host before the model finishes. If you raise the per-attempt timeout
above 1800000 ms via TRISS_REQUEST_TIMEOUT_MS or the MCP timeout_ms
argument, also raise tool_timeout_sec to at least 3 × your new value
plus headroom. The startup timeout only bounds process launch.

New installs write tool_timeout_sec = 5460 directly. Existing Codex
configs that still carry the historical tool_timeout_sec = 120 are
migrated automatically: the first triss mcp serve startup after
updating Triss (through any distribution path) upgrades that single value
in ~/.codex/config.toml and prints a notice. Only the root-level
[mcp_servers.triss] direct key counts — a tool_timeout_sec under the
[mcp_servers.triss.env] sub-table is an environment variable, never the
host timeout, and is left untouched. Because the host reads the config at
launch, restart any currently running Codex sessions once so they pick up
the new timeout. Values other than the exact historical 120 are never
overwritten — an exact root-level 120 is always treated as legacy,
since it is indistinguishable from a deliberately custom 120, and every
legacy exact-120 install is migrated by design.
Re-running triss mcp install --global --target codex is still available
as an optional repair route if you ever want to rewrite the block by hand
(see docs/mcp.md).

Scope: Project vs Global

A project-local install (./.mcp.json, only Claude) bakes
TRISS_PROJECT_ROOT into the launcher entry — fine, the file lives in
the project tree. A global install (~/.claude.json,
~/.codex/config.toml) is shared across every Claude Code / Codex
session, so it does not pin a sandbox path; the worker's project
root follows the per-session cwd set by the host. See
docs/mcp.md for the full
rationale and the migration note for older configs.

The exposed tool set is filtered by configured credentials:

  • Always (need only TRISS_WORKER_API_KEY): triss_chat, triss_ask,
    triss_fetch, triss_review, triss_commit_msg, triss_status.
  • triss_jira_* + triss_confluence_* when ATLASSIAN_* is set.
  • triss_linear_* when LINEAR_API_KEY is set.
  • triss_github_* when GITHUB_TOKEN is set (or gh CLI logged in).
  • triss_gitlab_* when GITLAB_TOKEN is set.
  • triss_coder_run + triss_coder_status when any coder provider key is
    set — TRISS_WORKER_API_KEY (the existing OpenAI-compatible worker),
    ZHIPU_API_KEY (Z.AI GLM), OPENCODE_API_KEY (OpenCode Zen or Go),
    MOONSHOT_API_KEY (Moonshot Kimi), or KIMI_API_KEY (Kimi for Coding)
    (setup: triss coder init). triss_coder_run takes an optional engine
    (opencode V1 default; --engine opencode2 beta — see
    opencode2.md — or crush); its timeout defaults to
    1500s (25 min) over MCP, above the CLI's 900s, since coding runs are
    expected to be long; override per call via the timeout arg. For
    runs that may exceed it, use triss coder run on the CLI instead.

Add credentials later → restart session → new tools appear automatically.

Full reference: docs/mcp.md.

The files under templates/ are what triss init and triss agent-help
render into other projects:
claude.md / codex.md are the nano variants written by init, and
claude-full.md / codex-full.md are the long cookbook served by
agent-help.

What it does

The expensive primary agent decides what to do. Triss does the reading
and writing
.

Recommended host-agent workflow

Keep one primary agent and one coder per implementation stream. You (the
expensive primary agent) understand the request, decide the plan, and own
architecture, authorization, and final acceptance; the coder owns the
repository investigation, implementation, tests, debugging, and
self-verification; you then inspect the actual diff and evidence and make
the final decision. Do not default to a researcher -> planner -> coder ->
verifier -> reviewer chain — use triss ask / triss fetch for
research-only work and triss review only when complexity, security
sensitivity, or regression risk materially improves confidence. Split work
across coders only when the streams are independently executable with
explicit merge or handoff boundaries. Prefer a fresh run without intentional
session reuse: pass the complete task packet to every run and rely on
--session / --continue only for deliberate continuation.

Pass the whole plan as one task packet — Goal, Plan, Constraints, Relevant
context, Success criteria, Validation, Return — via triss coder run --stdin
for long prompts or as the MCP prompt string:

triss coder run --stdin --isolate <<'TASK'
Goal
- Add the requested behavior.

Plan
- Follow the host-approved implementation steps.

Constraints
- Preserve existing public behavior outside the requested scope.
- Do not commit, push, deploy, or modify files outside this checkout.

Relevant context
- Known entry points, related files, prior findings, errors, or reference behavior.
- Include only context needed for this task; let the coder inspect the repository for the rest.

Success criteria
- Focused regression tests pass.
- The final diff contains only the requested change.

Validation
- Run the relevant repository-native focused tests.

Return
- Outcome, files changed, checks, and unresolved blockers.
TASK

triss agent-help prints the generated host-agent cookbook and the final
acceptance checklist.

Existing triss coder init installations keep their generated agent files
(init never overwrites them, so re-running it alone will not refresh
them). To adopt the stronger coder/researcher roles:

  • local scope: merge or replace ./.opencode/agents/coder.md /
    ./.opencode/agents/researcher.md;
  • global scope (the triss coder init default): merge or replace
    ~/.config/opencode/agents/coder.md /
    ~/.config/opencode/agents/researcher.md;
  • to regenerate them, back up or remove the generated files first, then
    re-run triss coder init with the matching explicit --local / --global
    scope.
Command Does Replaces
triss ask Reads files, URLs, and/or piped stdin — returns a summary The agent reading the source itself
triss exec Deterministically routes a task to ask, review, coder run, or chat; --explain prints the JSON decision without executing Manually choosing the delegation command
triss chat Bare prompt to the worker model — no corpus A separate gpt-style CLI
triss write Generates code/docs from a spec + reference file The agent typing out boilerplate
triss extract Pulls readable transcript from JSONL session logs Manually scraping ~/.claude/...
triss fetch Fetches URL(s) and returns readable markdown The agent's WebFetch tool
triss review Code review on a branch, PR, or explicitly piped diff (linked ticket only for branch/PR) The agent reading the whole diff
triss commit-msg Generates a commit message from staged diff Hand-writing or copy-pasting from web LLMs
triss usage Cumulative cost / token usage with per-project breakdown Squinting at stderr after each call
triss coder init Sets up a coding agent (default opencode V1 engine; --engine opencode2 for the V2 beta — shares the opencode.json config, see docs/engines/opencode2.md; --engine crush for crush): provider key/profile (--provider worker reuses TRISS_WORKER_*; Z.AI GLM default; Zen, Go, and Kimi are also supported), config, permission policy, and agent templates. Blocks (non-zero) on an unsafe existing opencode.json — missing deny-first bash policy (override with --allow-unsafe-bash) or a stale/cross-provider small_model. Manually installing/configuring opencode
triss coder run Spawns the coding agent (the OpenAI-compatible Triss worker, GLM, Kimi, OpenCode Zen, or OpenCode Go) and prints one JSON envelope (`--engine opencode opencode2
triss coder clean Removes finished .triss/wt isolation worktrees (--all forces all) Manually finding and deleting stale git worktrees
triss coder session Lists / cleans inactive v2 sessions per engine (`--engine opencode crush`)
triss coder result Lists / cleans retained result artifacts (enforced result-store quota) Finding result-store files by hand
triss coder state Section 15 rollback backup / validate for a project Manual backups before model transactions
triss coder models Lists the resolved engine/provider model catalogue (--json for scripting) Reading upstream model catalogues by hand
triss coder model Persists the main/small pair for the resolved engine (set) or restores a pinned version (rollback) Hand-editing opencode.json / crush.json
triss init Drops a tiny (~15 line) delegation block into CLAUDE.md / AGENTS.md Hand-writing routing rules
triss agent-help Prints the full delegation cookbook on demand (the nano block points here) A 200-line CLAUDE.md that always loads
triss status Shows current model + key + .env sources
triss update Checks for updates; explicitly applies/rolls back standalone installs npm registry polling or silent self-update
triss config Interactive credential management Manual .env editing
triss mcp Register Triss as MCP server in Claude Code Editing ~/.claude.json by hand
triss completion Shell completion script (bash/zsh) Hand-rolled completion

triss ask

triss ask --paths src/auth.ts src/db.ts \
          --question "List every place we read TRISS_WORKER_API_KEY"

triss ask --paths "src/**/*.ts" \
          --question "Find SQL injection risks" \
          --model pro --max-tokens 16384

triss ask --paths "src/**/*.ts" \
          --question "Find SQL injection risks" \
          --provider glm --model pro

triss ask --paths "src/**/*.ts" \
          --question "Find SQL injection risks" \
          --provider kimi --model pro    # Kimi K3 via MOONSHOT_API_KEY

# Optional evidence-oriented Markdown contract (text is the default)
triss ask --paths "src/**/*.ts" --question "Find SQL injection risks" \
          --format evidence

Typical output is a focused answer with cited file paths, not a raw file dump.
That is the whole trick: the primary agent gets the useful bits, not a
firehose wearing a moustache.

--format evidence appends a trusted instruction requiring the model-authored
Markdown sections Outcome, Evidence, Uncertainty, and Decision required.
It does not make Triss semantically validate the model's claims. The same
optional contract is available to triss review and MCP triss_ask /
triss_review as response_format: "evidence"; defaults remain unchanged.

triss exec

triss exec --explain --paths README.md "summarize this project"
triss exec --explain --review "review the current branch"
triss exec --code "add a bounded validation"

Repeat --paths <path> or --urls <url> when routing more than one source;
the final positional argument remains the task:

triss exec --paths README.md --paths package.json "summarize this project"

Routing is deterministic: explicit review inputs (--pr, --base,
--review) take precedence, then --paths/--urls for ask, --code, and
--chat. Without an explicit route, review/audit language selects review,
explicit implementation/change language selects coder run, and everything
else selects chat. Read-only status phrases such as show build status stay
on chat. Contradictory explicit signals and stdin-only routing fail
closed. Options unsupported by the selected route also fail instead of being
silently discarded. In --explain, such a failure is represented by
route: null with its reason rather than thrown. --explain emits
schema-versioned JSON and performs no model, Git, network, stdin, or filesystem
mutation.

exec --max-tokens is forwarded to ask, review, and chat. For coder routing it
is supported with --engine crush; the OpenCode engine has no per-run token
budget flag, so exec --code --max-tokens ... without Crush fails explicitly
instead of silently ignoring the requested cap.

triss write

triss write --spec "Pytest tests for auth.py covering OAuth2 happy path" \
            --context tests/test_main.py \
            --target tests/test_auth.py

triss extract

triss extract ~/.claude/projects/my-project/session.jsonl -o /tmp/chat.txt

triss commit-msg

git add src/foo.js src/bar.js
triss commit-msg                          # prints a Conventional Commits message
triss commit-msg --apply                  # prints + runs `git commit -m`
triss commit-msg --type fix --scope auth  # nudge the type/scope
triss commit-msg --no-conventional        # plain subject + body

Reads git diff --staged, sends it to the worker model with a Conventional
Commits-aware system prompt, prints the message. Defaults to your
TRISS_DEFAULT_MODEL preset.

triss usage

triss usage                          # last 24h: total tokens + $$$
triss usage --since 7d               # last week
triss usage --month                  # last 30 days
triss usage --by-project             # split by working directory
triss usage --by-model               # flash vs pro breakdown
triss usage --by-label               # ask / chat / review / commit-msg / …
triss usage --json                   # raw log records
triss usage --reset                  # clear the log

Every model call (CLI and MCP) appends one record to
~/.cache/triss/usage.jsonl. Records keep each token class the source
reported separately, instead of collapsing them into one prompt/completion
pair:

Triss usage · 1 call · last 24h

  total:         14,609

  input:
    uncached:       303
    cache read:  14,272
    cache write:      0

  output:
    visible:         19
    reasoning:       15

  cost:          unknown for 1 call (no complete cost) · engine reported $0.0000

The rule throughout is that unknown is not zero. A field the provider did
not report is null and is rendered as unavailable or as coverage
(reasoning: 930 · reported by 12/25 calls), never as 0. Crush, which
reports one combined count, is shown as combined, not as output.

Each record also carries the working directory, a label like triss/ask, and
a per-invocation call_id (UUIDv4). An optional parent_call_id lets a host
group several Triss calls under a single outer session — set
TRISS_PARENT_CALL_ID in the environment that launches Triss (e.g. in your
MCP server's env block) and every record from that process carries it.
External dashboards (e.g. tokentelemetry) can group by either field.

List prices for DeepSeek, PAYG GLM, and Kimi are baked in. GLM records retain
zai-coding-plan/ or zai/ so subscription usage stays known $0 while
unpriced PAYG usage is shown as unknown, never as free. Override per model
with TRISS_PRICE_<MODEL_ID>=uncached,cache_read,output or the four-value
uncached,cache_read,cache_write,output form (USD per token). Reports read
only the active log — the rotated usage.jsonl.old archive is excluded, and
the rotation default is 40 MiB. Disable tracking entirely with
TRISS_USAGE_LOG=0.

docs/usage-accounting.md is the full schema:
every provider's field mapping, cost precedence and completeness, legacy
records, and the deprecated compatibility fields.

Streaming output

Long --model pro calls (review, ask) stream tokens as they arrive when
stdout is a TTY, so you see progress instead of 1-3 minutes of silence.
--stream on ask, chat, or review forces streaming when stdout is
piped or redirected; without either flag, the TTY default remains in effect.
--no-stream disables streaming; if both forms are supplied, the last flag
wins. Streaming is automatically off for MCP tool calls.

For a buffered request that cannot stream, set TRISS_REQUEST_TIMEOUT_MS to
a positive integer timeout in milliseconds no greater than 2147483647.
Unset, invalid, zero, negative, and larger values retain the OpenAI SDK
default (600000 ms) for non-review calls; an unset GLM review instead runs
with the internal 30-minute per-attempt timeout (1800000 ms). An explicit
MCP timeout_ms always wins over both.

triss chat

triss chat "what's a JWT in one paragraph"
triss chat --model pro "design a rate limiter for ..."
triss chat --system "you are a postgres expert" "explain MVCC"
echo "long prompt..." | triss chat --stdin

Bare prompt to the worker model — no corpus, no retrieval, just a
direct call to chat(). Cheap one-shot lookups go here so the primary
model's budget stays on actual code work.

triss ask --stdin

The universal pipe input — any command's stdout can become the corpus:

git diff main..HEAD | triss ask --stdin --question "summarise the changes"
git log --since=1.week --stat | triss ask --stdin --question "what did I do?"
kubectl logs my-pod | triss ask --stdin --question "errors?"

Combine with --paths/--urls to mix sources in one round-trip. Triss
errors out if --stdin is used in a TTY — it always wants piped input.

triss review [PR]

Branch reviews use git diff against the selected base and may include a
linked Jira / Linear ticket auto-detected from the branch name. PR reviews use
gh pr diff plus PR metadata and may include a linked ticket from the PR title
(e.g. feature/ENG-42-foo → fetches ENG-42). Stdin mode is separate: it
reviews only the explicitly piped UTF-8 diff text and does not query or infer
Git, PR, branch, changed-file, or ticket metadata.

triss review                 # current branch vs auto-detected base
triss review 123             # GitHub PR #123 (requires `gh` CLI)
triss review --base develop  # explicit base
git diff main...HEAD | triss review --stdin  # review this branch's merge-base diff
triss review --skip-issue    # don't try ticket lookup
triss review --provider glm  # same review flow, one-shot GLM inference
triss review --provider kimi # …or Kimi (pro preset = kimi-k3)
triss review --files src/a.js test/b.test.js  # literal file selection (after --)
triss review --issue ENG-42  # explicit tracker issue (never inferred from prose)

Reliable delegation — review safety (review acceptance)

Review runs are bounded and fail closed (see the
docs/reliable-delegation-contract.md):

  • Limits: single request (256 KiB default / 1 MiB hard max), shard
    (96 KiB / 256 KiB), total corpus (4 MiB / 16 MiB), shard count (64 /
    1. — all reloadable via TRISS_REVIEW_*_BYTES / TRISS_REVIEW_MAX_SHARDS;
      any contradiction falls back to the complete default set.
  • Git: exact merge-base-to-head identity, one unique merge base, a
    sanitized environment (no external diff/textconv/config injection,
    grafts and nonempty shallow repositories rejected).
  • Selection: literal --files selectors are expanded across renames
    and only the selected content is acquired — a huge change with a small
    selected file never buffers the full diff first.
  • PRs: canonical input only, exact OID re-verification, disposable
    bare repository under a registry lock (3 concurrent runs, 120 MiB pack /
    128 MiB filesystem quotas); the source directory is never mutated.
  • Issues: PR or branch prose NEVER triggers tracker access. Only an
    explicit --issue KEY performs a bounded minimum-field lookup;
    --skip-issue is deprecated.
  • Empty responses fail with TRISS_PROVIDER_EMPTY instead of
    producing a clean verdict; usable non-empty text is never trimmed.

Sequential review sharding

triss review --payload-mode shard runs source-ordered whole-file shards
sequentially. A file is never split across shards; the first failure or
cancellation stops the sequence. Completed sharded execution is not a
global review
: there is no aggregation call, no cross-shard analysis, and
no global approval — the CLI prints global verdict: unavailable_for_sharded.
Partial errors carry completed shard verdicts only (never raw diff content).
evidence + shard and shard + --stream are rejected before any model call.

The three diff sources are mutually exclusive: local Git (triss review or
--base), a GitHub PR (triss review <PR>), or UTF-8 text piped to
triss review --stdin. --stdin cannot be combined with a PR number or
--base; --skip-issue remains accepted for compatibility but has no effect
in stdin mode because no ticket lookup occurs. Stdin mode rejects a TTY,
empty or whitespace-only input, and malformed UTF-8 before provider or model
resolution. It preserves accepted UTF-8 text exactly, without trimming or
line-ending normalization. Unpredictable per-request boundary markers keep
marker-like diff text inside the untrusted diff section rather than letting it
impersonate metadata or a linked ticket.

Defaults to the pro preset because review needs reasoning. Output is
a list of concrete issues with file:line citations — not a diff
summary. GLM reviews auto-size the output budget (up to 64 KiB for a single
review and 32 KiB per shard), so omitting --max-tokens is recommended. If you
pass it explicitly, use at least 16384; that disables auto-sizing and the
generic 8192-token value can be exhausted by reasoning. Narrow the base/scope
as well when only a remediation commit needs review. Cost: a 25KB diff review on
pro runs ~$0.005-0.01 with
prompt caching.

Example shape:

Findings
- src/auth.js:42 accepts an expired token because ...
- test/auth.test.js:88 covers the happy path but not ...

Residual risk: ...

triss fetch / triss ask --urls

# Just clean markdown
triss fetch https://api-docs.example.com/

# Fetch + summarise via DeepSeek
triss fetch https://blog.example.com/long-post --question "key takeaways?"

# Mix URLs with files (or several URLs together)
triss ask --urls https://spec.example.com/v2 https://spec.example.com/v3 \
          --paths README.md \
          --question "what's missing from README that's in the spec?"

HTML is stripped of <script>, <style>, <nav>, <aside>, <footer>,
forms, and SVG; <main> / <article> are preferred when present;
non-HTML responses (JSON, plain text) are returned verbatim. 30-second
default timeout, configurable via --timeout <ms>.

triss coder

Delegates an implementation task to a cheap coding agent — the existing
OpenAI-compatible Triss worker, GLM, Kimi,
OpenCode Zen, or OpenCode Go models (the opencode V1 engine by default;
opencode2 beta — see docs/engines/opencode2.md — or crush; see
Engines below) instead of the primary model writing
the code itself.

triss coder init                                  # once: key, opencode.json, agent templates
triss coder run "add input validation to /signup" --isolate
triss coder run "..." --engine crush              # crush engine (isolates by default; restrict is opt-in)
triss coder run "..." --engine crush --restrict   # crush + CLI allowlist on top of the worktree
triss coder clean                                 # remove finished isolation worktrees
triss coder session list                          # list v2 sessions (per engine)
triss coder session clean <slug> --engine opencode # remove one inactive isolated session
triss coder result list                           # list retained result artifacts
triss coder state backup --project <path>         # Section 15 rollback backup
triss coder state validate --project <path> --backup <dir>

Every triss coder run envelope on the opencode and crush engines
(and the matching MCP tool) carries the session acceptance contract fields:
session_slug (explicit slug or a generated per-run slug — never an
implicit persistent conversation), result_retention
/ result_id (retained only for isolated changed runs with enforced
result-store quota and a successful reservation), and execution_capabilities
(eight honest enforced|best_effort|unavailable values plus
effective_isolation). The opencode2 beta engine still returns the older
envelope shape (session_id, exit_reason, final_text, files_changed,
diff_stat, worktree, usage, warnings) without these fields — use its
files_changed / diff_stat / worktree as evidence there. Non-isolated files_changed is null; the only
changes-expectation evidence is run_files_changed. Process completion and a
non-empty final text are not task satisfaction — use --isolate, check
run_files_changed in the envelope, and verify the retained worktree/diff
directly when the envelope returns one (a run with worktree: null and an
empty run_files_changed — or empty files_changed on the opencode2 beta
— produced no retained deliverable): git status --short,
then review the staged patch with git diff --cached and any unstaged
changes with git diff (Triss stages the deliverable changes before
returning the envelope). Unavailable OS sandbox/cleanup/lock/quota does not block a
non-isolated/best-effort run but provides none of those guarantees; explicit
or default isolation needs --allow-best-effort-caller-worktree (default
off) or fails before spawn with TRISS_CODER_ISOLATION_ENFORCEMENT_REQUIRED
(stable err.code; retry hint when the isolation mechanism is unavailable),
and unavailable credential isolation always blocks before spawn. With the
opt-in and only when the isolation mechanism itself is unavailable (no git
repository or worktree creation failure — slug/branch conflicts like
already exists still fail closed), the run downgrades to
best_effort_caller_worktree: stderr and envelope warnings carry
TRISS_CODER_ISOLATION_DOWNGRADED and effective_isolation becomes
best_effort_caller_worktree (advisory-only, files_changed is null,
edits may reach the caller worktree). Full details are in the
docs/reliable-delegation-contract.md.

triss coder init first asks which provider to configure — Z.AI GLM
(default), the existing Triss worker (--provider worker, aliases
openai / openai-compatible), OpenCode Zen (--provider opencode-zen, free rotating
models), OpenCode Go (--provider opencode-go, paid subscription),
Moonshot Kimi (--provider moonshot, pay-as-you-go
moonshotai/* models like kimi-k2.7-code), or Kimi for Coding
(--provider kimi-for-coding, the flat-rate subscription serving Kimi K3).
For Z.AI it probes which plan your key works with (subscription vs.
pay-as-you-go) and writes the matching model prefix; Zen and Go share
OPENCODE_API_KEY but use distinct opencode/<id> and opencode-go/<id>
catalogues; the two Kimi
providers need no probe at all — their plans use different keys
(MOONSHOT_API_KEY vs KIMI_API_KEY), so the choice already names the
endpoint. Either way it lets you pick the model interactively. See the
Providers section below and
docs/engines/opencode-zen.md and
docs/engines/opencode-go.md for the OpenCode provider deep-dives.

Prints one JSON envelope to stdout — files_changed, diff_stat, and
worktree tell you what to review; --isolate runs the agent in a
disposable .triss/wt/<slug> git worktree so it never touches your
working tree directly. Before returning the envelope, Triss terminates and
waits for any residual process in the selected engine's process group, so tests or DB
clients cannot keep locks or write files after completion. MCP cancellation is
forwarded to the same cleanup path. --session <slug> continues the same opencode
conversation across calls. POSIX only (macOS/Linux) for now. See
the GLM client guide
for the full picture of how Triss talks to GLM
(all engines, key/endpoint routing, models, and every usage mode),
docs/configuration.md for the coder env vars, and docs/mcp.md for the
MCP tool equivalents.

Enginesopencode (default) enforces a deny-first bash allowlist
(opencode.json) that actually works — prefer it when you want that safety
layer baked in. crush (--engine crush / TRISS_CODER_ENGINE=crush, npm
@phpcraftdream/crush ≥0.1.3) has a weaker, interim safety story: live
testing proved crush 0.1.3 ignores its permissions.run config block and
a denied bash command deadlocks to the timeout. So triss ships crush with
isolate-ON by default (the disposable worktree is the reliable safety
layer) and makes restrict opt-in (default OFF). triss coder init still
seeds a permissions.run block into crush.json as forward-compat (harmless,
correct once upstream honors it), but the working allowlist today is the CLI
flags: when you pass --restrict (or TRISS_CODER_CRUSH_RESTRICT=1), triss coder run emits --restrict-run plus --allow-bash/--allow-tool flags for
each entry. Override per-run with --restrict / --no-restrict (resolution:
CLI flag > env > crush.json permissions.run.restrict > default OFF). For
Z.AI GLM, the opencode engines and crush all use the single ZHIPU_API_KEY
(crush ≥0.1.1 reads it natively; triss also forwards it as ZAI_API_KEY
for older binaries; see
Providers below for the opencode-only OpenCode alternatives). See the
Crush engine guide for the supported configuration,
safety boundaries, and current upstream limitations.

Providers — the opencode engine isn't limited to Z.AI. The required
API key follows the model's <provider>/ prefix: triss-worker/* reuses
the existing TRISS_WORKER_API_KEY + TRISS_WORKER_BASE_URL profile;
zai-coding-plan/* and
zai/* (GLM) use ZHIPU_API_KEY; opencode/* models — served free by
OpenCode Zen — and paid opencode-go/*
models use the shared OPENCODE_API_KEY;
moonshotai/* (and the China-mainland moonshotai-cn/*) Kimi models use
MOONSHOT_API_KEY; and kimi-for-coding/* models — the flat-rate
Kimi for Coding subscription, e.g.
kimi-for-coding/k3 (Kimi K3) — use KIMI_API_KEY. Zen ids rotate
freely, so discover the current id and pass it rather than hard-coding one:

triss coder init --provider worker
triss coder run "mechanical task" \
  --provider worker --model triss-worker/deepseek-v4-flash

The worker route uses Chat Completions through @ai-sdk/openai-compatible.
It creates no second API key and is supported by the OpenCode engine only.
After changing the worker base URL or flash/pro model ids, rerun
triss coder init --provider worker; coder model set --provider worker
fails closed until the matching env-backed provider block is present. Global
init reads only global worker settings (except genuine shell exports) and
rejects a conflicting higher-precedence project provider. Every worker run
revalidates the registered global/project endpoint and model allowlist before
forwarding the key, and prints an exact scope-specific init command when the
saved provider is missing or stale. The broader runtime-tree snapshot described
below applies to explicit one-shot --provider worker runs.

Worker init is a one-time provider registration, not an exclusive provider
choice: GLM and worker credentials/configuration can coexist. After the worker
provider has been registered, switch the complete main/small pair for one task
without changing the persistent default:

# Worker for this task; small defaults to the same model.
triss coder run "mechanical task" \
  --provider worker --model triss-worker/deepseek-v4-flash

# GLM for this task, with an explicit fast model.
triss coder run "hard task" \
  --provider zai --model zai-coding-plan/glm-5.2 \
  --small-model zai-coding-plan/glm-5-turbo

--provider is OpenCode-only, requires a provider-qualified --model, and
never rewrites .env or opencode.json. --small-model is available only
with --provider; when omitted it equals the one-shot main model. The worker
run still validates the previously registered env-backed provider before the
key is forwarded. During a one-shot provider run, Triss first audits every
file-backed source loaded by the pinned OpenCode version: global config.json
and opencode.json(c), ~/.opencode/opencode.json(c), and runtime-directory
ancestors up to the Git root (or / outside Git). It then asks OpenCode for the
final merged config under the exact sanitized child environment, with a random
canary instead of the real credential, and verifies the final main/small models
and selected provider. Both the preflight and actual run use --pure to disable
external plugins. Unreadable/JSONC/unknown layers fail closed. Concurrent
same-user config mutation between preflight and spawn remains outside this
guard's threat model.

triss coder init --provider opencode-zen              # guided: key + opencode.json
triss coder models --provider opencode-zen            # see live Zen ids
triss coder run "..." --model opencode/<current-id>   # per-run override

OpenCode Go uses a separate paid catalogue and prefix despite sharing the key:

triss coder init --provider opencode-go
triss coder models --provider opencode-go
triss coder run "..." --model opencode-go/deepseek-v4-flash

A configured key does not by itself prove that the Go subscription or the
workspace regional-hosting opt-in is active. Triss leaves those account
settings untouched and reports inference-time provider errors verbatim. Go
init fails closed on 401/403, malformed responses, and an authoritative empty
catalogue. Temporary network or HTTP 408/429/500/502/503/504 failures require an explicit
triss coder init --provider opencode-go --allow-unverified --global (or
--local) before Triss will use its built-in Go fallback.

Kimi works the same way:

triss coder init --provider moonshot             # pay-as-you-go: kimi-k2.7-code default
triss coder init --provider kimi-for-coding      # subscription: Kimi K3 on a flat plan
# …or per-run, without changing the default:
triss coder run "..." --model moonshotai/kimi-k3
triss coder run "..." --model kimi-for-coding/k3

triss coder run passes the resolved model to opencode with --model and
forwards only the key that model needs — no Z.AI key is required for Zen, Go, or
Kimi runs. A shell-exported TRISS_CODER_MODEL is a runtime override of the
MAIN model only (it sits in the OpenCode-main precedence chain: one-run --model
→ shell TRISS_CODER_MODEL → project .triss.env → global .env → built-in
default), so it changes the main model for every run until unset.
TRISS_CODER_SMALL_MODEL is setup intent consumed by triss coder init /
triss coder model — it does not swap the small model mid-run (opencode reads
small_model from opencode.json). Use --model alone for a one-run main-only
override within the current provider; use --provider + --model and optional
--small-model to switch the complete pair for one run. The deny-first
opencode.json bash policy applies to every provider.
Full details, the model catalogue, and every configuration path are in
docs/engines/opencode-zen.md and docs/engines/opencode-go.md.

If your Z.AI plan hits its usage limit, triss coder run fails fast with
the reset time converted to your local timezone (Z.AI reports it in
Beijing time), instead of hanging until --timeout. Under the hood
opencode retries the throttled call silently, so the reset time is read
from the engine log and the run is killed within a few seconds of the
limit.

Model management — engine vs provider. Two independent axes; most
confusion is conflating them:

  • Engine = how the agent is launched: opencode (default),
    opencode2 (beta), or crush. Set at triss coder init --engine …
    or per run with triss coder run --engine ….
  • Provider = which API serves the model: Triss worker, Z.AI GLM, OpenCode Zen, OpenCode Go,
    Moonshot Kimi, Kimi for Coding. Register/set the persistent default with
    triss coder init --provider …, or select a complete one-shot pair with
    triss coder run --provider … --model … [--small-model …].

Not every engine speaks every provider:

Engine Providers served
opencode Triss worker, Z.AI GLM, OpenCode Zen, OpenCode Go, Moonshot, Kimi for Coding
opencode2 Same provider routing as V1 (shares opencode.json; one-shot --provider / --small-model overlays rejected — see docs/engines/opencode2.md)
crush Z.AI GLM (coding-plan only)

triss coder init drives setup in that order — engine, then provider,
then it asks for only that provider's credential
and writes the matching
model prefix (triss-worker/<id>, opencode/<id>, opencode-go/<id>, zai-coding-plan/*, moonshotai/*, or
kimi-for-coding/*).

Choosing a model. --model by itself on triss coder run remains a
single-run override of the main model only. For a non-persistent provider
switch, pass --provider with a provider-qualified --model; add
--small-model when the small role should differ, otherwise it defaults to the
one-shot main. To persist a choice, use triss coder model set — positional
main plus --small — which requires the engine and scope explicitly:

# global, opencode engine: positional main + --small; --yes for noninteractive use
triss coder model set --engine opencode --global \
  opencode/<id> --small opencode/<id> --yes
# local, crush engine: canonical coding-plan GLM pair
triss coder model set --engine crush --local \
  zai-coding-plan/glm-5.2 --small zai-coding-plan/glm-5-turbo --yes

Discovering models. triss coder models lists what the resolved
engine/provider offers for that invocation, with filters and a
machine-readable form:

triss coder models                          # current effective engine/provider
triss coder models --engine opencode        # resolved provider for the OpenCode engine
triss coder models --provider opencode-zen  # just OpenCode Zen
triss coder models --provider opencode-go   # paid OpenCode Go catalogue
triss coder models --json                   # for scripting

When a Zen model goes stale. Free OpenCode Zen models rotate — no
specific id is guaranteed to stay (the once-free opencode/hy3-free
Hunyuan model is the canonical stale-model incident). If a model is
removed upstream, recovery stays inside Zen, not a silent jump to
GLM. See what is live and re-pick explicitly:

triss coder models --provider opencode-zen       # current Zen ids
triss coder model set --engine opencode --global \
  opencode/<current-id> --small opencode/<current-id> --yes

Triss surfaces that replacement command rather than auto-switching you
to GLM.

Full flag reference, the model catalogues, key/endpoint routing, and
the stale-model recovery flow are in the
GLM client guide,
docs/engines/opencode-zen.md, docs/engines/opencode-go.md, and
docs/configuration.md.

Integrations

External-service plugins live under src/integrations/<name>/. They are
auto-discovered at startup and appear as top-level subcommands.

Integration Subcommand Operations Reference
Jira triss jira search, issue, create, update, comments, transitions, attachments, whoami docs/integrations/jira.md
Confluence triss confluence search (CQL), page, create, update, spaces docs/integrations/confluence.md
Linear triss linear search, issue, create, update, comments, states, attachments, projects, initiatives, milestones, labels, bulk-update docs/integrations/linear.md
GitHub triss github search, issue, create, update, comments docs/integrations/github.md
GitLab triss gitlab search, issue, create, update, comments docs/integrations/gitlab.md

Two design rules:

  • Read commands accept --question — instead of dumping the raw API
    response, Triss runs it through DeepSeek and returns a focused summary.
  • Write commands stay directcreate, update, comments --post,
    transitions --apply make HTTP calls without LLM in the loop.

triss status shows each integration's env-var readiness so you know what
still needs configuring.

triss agent-help inlines per-integration delegation rules into the full
cookbook only for integrations whose credentials are present. Add a
Linear key later? Run triss config wizard linear, then the next time the
agent runs triss agent-help the Linear section appears automatically.
Users who never use Jira never see Jira instructions in the cookbook.

(The nano triss init block stays the same regardless — integration
hints live in the on-demand cookbook, not in the always-loaded block.)

Adding your own integration

The plugin contract is one folder + one file. A working GitHub Issues
integration in ~80 lines is documented end-to-end in
extension guide.
High-level recipe:

  1. Create src/integrations/<name>/index.js.
  2. export default { name, description, envVars, register(program, { wrap }) {}, agentInstructions: { claude, codex } }.
  3. Use the helpers in src/integrations/_contract.js
    (httpJson, requireEnv, summarize, printResult,
    IntegrationError).
  4. Drop tests in test/<name>-*.test.js (mock globalThis.fetch).
  5. Run triss --help — your subcommand appears automatically. The
    wizard, triss status, and triss agent-help (full cookbook) all
    pick up the new manifest with no further wiring.

Models

By default, Triss exposes two presets so you can switch quickly:

Preset Default model Use for
flash deepseek-v4-flash Bulk reads, summaries, doc updates
pro deepseek-v4-pro Harder analysis, careful generation

Pick a preset per call:

triss ask   --paths ... --question "..." --model flash   # default
triss write --spec   ... --target   ...   --model pro

If DeepSeek renames the models again, or you want to point Triss at a
different provider, override the names without touching code. Triss only
requires an OpenAI-compatible chat-completions endpoint.

You can also pass any model id directly: --model deepseek-v4-pro.

ask and review can route the same one-shot request to GLM or Kimi without
invoking the agentic coder runtime:

triss ask --paths ... --question "..." --provider glm --model flash
triss review --provider glm --model pro
triss review --provider glm --model zai/glm-5.2  # pay-as-you-go endpoint
triss review --provider kimi                     # pro preset → kimi-k3
triss ask --paths ... --question "..." --provider kimi --model flash  # kimi-k2.6

GLM reviews auto-size the output budget (up to 64 KiB single / 32 KiB per shard) so
omitting --max-tokens is the recommended default. If you pass --max-tokens
explicitly the auto-budget is disabled — use at least 16384 (the generic 8192 can be
exhausted by reasoning and return an empty verdict); for a large PR, also narrow
--base to the change that needs re-review.

One-shot ask / review output is provider-shape tolerant: Triss emits the
assistant text whether the successful response carries OpenAI-style
choices[0].message.content or a top-level final_text. A present
final_text must never be treated as an empty response or dropped by the CLI
or MCP renderer.

For GLM, pro maps to glm-5.2 on both endpoints, while flash — the cheap
bulk-read tier — maps to glm-4.7 on the subscription endpoint and to
glm-4.5-air ($0.20/$1.10 per 1M) on pay-as-you-go. The subscription endpoint
serves a glm-4.5-air request as glm-4.7, so the preset names what actually
runs there.

ZHIPU_API_KEY is reused. Prefix an explicit model with zai-coding-plan/
or zai/ to select the subscription or pay-as-you-go endpoint; otherwise
Triss inherits the prefix from TRISS_CODER_MODEL and falls back to the
coding-plan endpoint. A Z.AI key does not say which plan it belongs to, so
when nothing pinned the endpoint and the call comes back 401/403/429,
Triss retries once on the other endpoint, prints which one worked, and reuses
it for the rest of the process. Pin it (TRISS_CODER_MODEL=zai/glm-5.2, or run
triss coder init) to skip that probe. triss status shows the resolved
endpoint, where it came from, and the presets it selects.

For Kimi (--provider kimi, alias moonshot), pro maps to kimi-k3
Moonshot's flagship open-weights model ($3.00/$15.00 per 1M tokens, cache-hit
input $0.30) — and flash to kimi-k2.6 ($0.95/$4.00, cache-hit $0.16), the
cheapest current-generation model on the platform. MOONSHOT_API_KEY is
reused from the coder setup, there is a single OpenAI-compatible endpoint
(https://api.moonshot.ai/v1; set TRISS_KIMI_BASE_URL for the
China-mainland api.moonshot.cn), and model ids are passed bare —
--model kimi-k2.7-code. The Kimi for Coding subscription is coder-only: its
endpoint speaks the Anthropic protocol, which ask/review's OpenAI client
cannot use.

triss coder stays separate because it is an agent runtime with tools,
sessions, and worktree isolation.

Provider recipes

DeepSeek (default, recommended)

triss config set TRISS_WORKER_API_KEY                     # masked prompt
# That's it — BASE_URL / FLASH / PRO use the current DeepSeek V4 defaults.

Kimi / Moonshot (first-class)

triss config set MOONSHOT_API_KEY                         # masked prompt
triss ask --provider kimi ...                             # flash=kimi-k2.6, pro=kimi-k3

Or replace the worker entirely (keeps --provider free for something else):

triss config set TRISS_WORKER_API_KEY $MOONSHOT_API_KEY
triss config set TRISS_WORKER_BASE_URL https://api.moonshot.ai/v1
triss config set TRISS_WORKER_FLASH_MODEL kimi-k2.6
triss config set TRISS_WORKER_PRO_MODEL kimi-k3

Ollama (local, free)

triss config set TRISS_WORKER_API_KEY ollama
triss config set TRISS_WORKER_BASE_URL http://localhost:11434/v1
triss config set TRISS_WORKER_FLASH_MODEL qwen2.5-coder:14b
triss config set TRISS_WORKER_PRO_MODEL qwen2.5-coder:32b

OpenRouter (any model, one key)

triss config set TRISS_WORKER_API_KEY $OPENROUTER_API_KEY
triss config set TRISS_WORKER_BASE_URL https://openrouter.ai/api/v1
triss config set TRISS_WORKER_FLASH_MODEL deepseek/deepseek-v4-flash
triss config set TRISS_WORKER_PRO_MODEL anthropic/claude-sonnet-4.6

Add --local to scope any of these to the current project only
(e.g. one repo on Ollama, the rest on cloud DeepSeek).

Environment reference

triss config wizard writes the env file for you — most users never
touch the variables directly. The full reference (worker model,
integrations, tunables, security toggles) lives in
docs/configuration.md.

TRISS_UPDATE_CHECK=0 disables passive update checks. Installer-only
TRISS_STANDALONE_HOME and TRISS_BIN_DIR select standalone paths and are
recorded in the ownership receipt; later environment changes do not grant write
authority.

.env files are loaded from ~/.config/triss/.env (global) and
<project-root>/.triss.env (project, overrides global). Real process.env
always wins. See docs/configuration.md
for recipes (per-project Jira, CI, switching providers).

Cost in practice

Two weeks of opencode engine usage (Aug 4–18, 2026)

The headline numbers first — what triss coder actually burned across
the last 14 days, aggregated from the local OpenCode database:

Model family Requests All tokens Excluding cache reads Recorded cost
DeepSeek (opencode + opencode-go) 43,357 4.23B 217.7M $24.06
GLM (zai-coding-plan + opencode-go) 4,716 278.4M 21.0M $5.90
Total 48,073 4.51B 238.6M $29.96

~95% of the 4.51B tokens are cache reads (4.27B) — repeated context
served at a fraction of uncached input cost. The non-cached working set
across two weeks of agentic coding was ~239M tokens. Recorded cost is what
OpenCode stores (quota usage on subscriptions, not necessarily cash paid).

How these numbers were computed. Aggregated from the local OpenCode
SQLite database (~/.local/share/opencode/opencode.db) over
2026-08-04 00:00 → 2026-08-18 23:59 local time, counting assistant
messages with non-zero usage. Input / output / reasoning / cache-read /
cache-write are additive token categories; opencode-go appears under
both rows because it is the provider channel, and each model family is
bucketed by the resolved model, not the channel. Reproduce with the
read-only report script in the opencode-usage-report skill
(--days 14).

An earlier example week (the Triss worker)

One full week of real usage on this codebase, captured from the DeepSeek
dashboard (May 6–13, 2026, all at the list price then in effect):

Metric Pro Flash Total
Requests 143 66 209
Input tokens 3.74M 2.10M 5.84M
↳ cache hits 1.08M 256 1.08M
Output tokens 833K 156K 990K
Cost (USD) $1.88 $0.34 $2.22

That is ≈ 1¢ per request on actual day-to-day work — bulk reads,
code reviews, tracker lookups, commit messages, web fetches. The same
volume through the primary agent would have run roughly:

Primary model Input (per 1M) Output (per 1M) Est. cost for the same week
Sonnet 4.6 $3 $15 ~$32 → 14× more
Opus 4.7 $15 $75 ~$161 → 70× more

The actual saving is larger than the ratio above, because Triss returns
a 1–2K-token summary — so the primary model's context never carries the
raw 5.8M input. That compounds across turns.

One concrete request

For reference, here is a single measured call of the kind that drives
the weekly numbers above:

Task Source bytes DeepSeek (pro, list price) Same job in Opus 4.x
triss ask --urls --paths over the original claude-coworker-model README + 12 of our source files (18.3K in / 2.4K out, structured 4-section report) ≈ 65 KB $0.040 ≈ $0.45

Real savings depend on which operations you delegate (bulk reads win
the most; tiny lookups break even); see templates/claude.md for the
rules of thumb.

Security & privacy

The short version for a vendor security review — full details in
SECURITY.md:

  • Local-first. Triss is a CLI/MCP server on your machine, not a hosted
    service. It stores nothing server-side and has no telemetry — zero
    data goes to the Triss developers.
  • Outbound data is explicit and documented. Model commands and coder
    engines may send selected repository content to the configured provider;
    integrations call their configured services; a credential-free GitHub
    Releases check runs when the update cache is due. The complete recipient,
    payload, trigger, and opt-out table is in
    docs/data-flows.md.
  • Data residency is a config option. Need an EU processor, a DPA, or
    zero retention? Point the worker at Azure OpenAI, Bedrock, Mistral, or a
    self-hosted model — see provider recipes.
  • Usage log is metadata-only. ~/.cache/triss/usage.jsonl records
    tokens and cost, never prompt or file content. TRISS_USAGE_LOG=0
    disables it.
  • Guardrails. SSRF guard on all agent-controlled fetches, path sandbox
    in MCP mode, response-size caps, secret masking in output. Residual risks
    are documented, not hidden.
  • Auditable supply chain. npm contents are allowlisted and smoke-tested;
    the standalone artifact has a deterministic source-to-artifact pipeline.
    Direct and transitive npm dependencies remain part of the installed code.

Report vulnerabilities via GitHub Security Advisories
(SECURITY.md).

Roadmap

Shipped — see the Tools table for usage:
Claude Code support · Plugin-style integrations · Interactive credential
management with per-project overrides · Web fetching · Standard/Advanced
wizard · bash + zsh completions · --stdin · triss review [PR] ·
triss chat · MCP server · Cost tracking · triss commit-msg · GitHub /
Confluence / GitLab integrations · Streaming output for ask/chat/
review · Codex AGENTS.md rules · Path-safety sandbox in MCP mode ·
test suite · Reliable delegation — coder envelope v2, session/result stores,
credential proxy, bounded review corpus limits, exact
merge-base diff identity, disposable PR bare repos, and sequential
whole-file review sharding · triss exec deterministic routing ·
triss coder (opencode V1 default, opencode2 beta, crush) with worktree
isolation · --format evidence · Kimi for Coding subscription ·
provider recipe blocks for Kimi, Ollama, and OpenRouter.

Planned:

  • Crush upstream permissions.run enforcement (currently inert —
    the working allowlist is the CLI --restrict flags).
  • opencode2 beta graduation: real credential isolation and
    fixture-verified subagent support (see docs/engines/opencode2.md).

Contributing and security

Contributions are welcome; start with
CONTRIBUTING.md
for local setup, test commands, and the project conventions.

Security-sensitive changes deserve extra care because Triss sits between an
agent, your filesystem, web URLs, and tracker credentials. See
SECURITY.md
for the reporting path and the current trust
boundaries.

Changelog

Release notes live in CHANGELOG.md. The format follows
Keep a Changelog and the project
uses Semantic Versioning.

Acknowledgements

Original idea & rationale: Kunal Bhardwaj — I was burning through Claude
Code's weekly limit in 3 days
,
based on imkunal007219/claude-coworker-model.

License

MIT — see LICENSE.

Yorumlar (0)

Sonuc bulunamadi