Skip to content

feat: MCP-first data tools with a model-free CLI fallback and workspace skills - #11

Open
hkaltai wants to merge 12 commits into
mainfrom
tool-cli-plugin
Open

hkaltai wants to merge 12 commits into
mainfrom
tool-cli-plugin

Conversation

@hkaltai

@hkaltai hkaltai commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Gives Claude Code direct access to altimate-code's data tools instead of delegating each task to a second altimate-code agent with its own model. The plugin uses the altimate-code MCP server when it is allowed, falls back to the model-free altimate-code tool run CLI when an organisation blocks MCP servers, and brings the linked Altimate workspace (knowledge, conventions, memory and team skills) into the session in both modes. Delegation to the altimate-code agent remains for long multi-step dbt jobs.

Requires an altimate-code build with mcp serve and the tool CLI: AltimateAI/altimate-code#1609. Builds on #6 (MCP registration, analyst agent).

Changes

Data tools: MCP first, CLI fallback

  • .mcp.json registers altimate-code mcp serve --workspace-tools (read-only by default).
  • The SessionStart hook (hooks-handlers/data-mode.sh) picks the mode without starting the CLI: CLI mode when altimate-code is not on PATH, when managed, user or project settings deny the server (deniedMcpServers, allowedMcpServers without it, disabledMcpjsonServers), or with ALTIMATE_DATA_MODE=cli. Only CLI mode adds routing guidance (tool context, then tool run <tool> --args <json>).
  • The altimate-code skill, the analyst agent and /altimate-code:altimate use the MCP tools when present and tool run otherwise; long jobs still use the builder agent.
  • Opt-in PreToolUse guard (ALTIMATE_ROUTE_GUARD=1) points direct warehouse client commands at tool run.

Linked Altimate workspace in both modes

  • workspace_context, workspace_skill and workspace_execute over MCP or tool run --workspace-tools, with handling for each setup status (needs_auth, needs_workspace, disabled, unavailable, needs_engine). Memory is saved only on an explicit request.
  • Workspace skills become Claude Code project skills: SessionStart copies them from the workspace snapshot into .claude/skills/, sanitised (frontmatter reduced to name and description, ! command blocks disarmed, no hook, agent, command or settings files), only for the signed-in tenant, never replacing a user-written skill, and kept out of git. altimate-code #1609 also writes these copies when a project is linked or refreshed, so they exist before the first session.
  • Refresh never blocks the session: a background refresh when the snapshot is missing or over an hour old, an hourly refresh from a Stop hook in long sessions, and /altimate-code:refresh-skills on demand. ALTIMATE_CLAUDE_SKILL_SYNC=0 turns copying and refresh off.

Also included

  • README, CONTRIBUTING and PRIVACY updated for the MCP server and its data flows.
  • Version 1.4.0, with the changes in plugins/altimate-code/CHANGELOG.md.

The automatic pilot listing (altimate-code-experimental) from #9 is not part of this PR; it stays in #9.

Validation

  • tests/data-mode.sh, tests/session-start.sh, tests/refresh-skills.sh, tests/warehouse-guard.sh, tests/resolve-cli.sh, tests/workspace-tools.sh pass; python3 -m pytest tests/test_sync_workspace_skills.py 17/17; claude plugin validate passes for the marketplace and the plugin.
  • Live Claude Code sessions: a skill written by the background refresh mid-session is used in the same turn; /altimate-code:refresh-skills runs and reports the copies; MCP mode and CLI mode each answered workspace questions correctly against a #1609 build.
  • Benchmarks with Claude Code (Sonnet 4.5) against a build of #1609:
    • 100 dbt and warehouse tasks: routing to altimate-code rose from 55/75 to 74/75 in MCP mode and 75/75 in CLI mode, with no false positives on the 25 tasks that should not use it; accuracy unchanged (94–95/100).
    • Questions that need workspace skills: the team skills were available at the start of every session (100/100), and accuracy matched the existing MCP flow (58% vs 55% on 100 questions) at 12% lower cost per run. Without workspace skills, Claude Code answered 15% of these correctly.

Known limitations

  • If an altimate-code without mcp serve is on PATH, the hook still picks MCP mode; the server fails to start and Claude Code caches that failure until restarted.
  • Curl installs expose only altimate; MCP mode needs the altimate-code name on PATH (CLI mode works with either).

🤖 Generated with Claude Code

Do not merge: experiment for evaluating direct altimate-code tools in Claude Code.

- Bring in the MCP registration, analyst agent and experimental listing from the plugin draft branches
- Skill and analyst agent use the altimate-code MCP tools when present, otherwise `tool context` then `tool run`
- SessionStart hook picks MCP or CLI mode without starting the CLI and adds routing guidance only in CLI mode
- Opt-in PreToolUse guard for direct warehouse clients (`ALTIMATE_ROUTE_GUARD=1`)
- Tests: `tests/data-mode.sh`, `tests/warehouse-guard.sh`

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hkaltai and others added 4 commits October 28, 2026 17:09
- Start the MCP server with --workspace-tools
- Pass --workspace-tools on every tool run/list/schema call in CLI mode (not tool context)
- Skill: workspace_context, workspace_skill and workspace_execute in both modes, receipt refresh, setup statuses, engine install on request, linking without memory upload, skill list/refresh/publish, memory save only on explicit request
- Analyst agent, /altimate command and SessionStart text route workspace questions to the workspace tools
- Tests: tests/workspace-tools.sh

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n both modes

Do not merge: experiment.

- SessionStart copies the linked workspace's skills into `.claude/skills` in MCP and CLI mode (ported from the workspace-skills draft: command blocks neutralised, signed-in tenant only, user skills never overwritten); `ALTIMATE_CLAUDE_SKILL_SYNC=0` disables it
- Starts a bounded background `workspace refresh` when the snapshot is missing or older than an hour
- `.mcp.json` runs `mcp serve --workspace-tools`; skill and analyst agent describe workspace context, skills and reads in both modes
- Tests: `tests/session-start.sh`, `tests/test_sync_workspace_skills.py`; version 1.4.0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…and on demand

Do not merge: experiment.

- `hooks-handlers/refresh-skills.sh` refreshes the linked workspace's skills and copies them into `.claude/skills`: `--if-stale` runs in the background when the snapshot is missing or over an hour old, `--wait` refreshes now and reports the copies; one refresh per project at a time
- SessionStart copies the snapshot already on disk and starts the background refresh without waiting; Claude Code loads skills added mid-session
- Stop hook runs the same hourly background refresh in long sessions
- `/altimate-code:refresh-skills` command for a manual refresh
- Tests: `tests/refresh-skills.sh`

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…refresh

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@hkaltai hkaltai changed the title [DO NOT MERGE] Experiment: MCP-first plugin with a CLI fallback feat: MCP-first data tools with a model-free CLI fallback and workspace skills Oct 29, 2026
The `altimate-code-experimental` listing, its packaging script, docs and smoke
tests belong to the separate pilot PR; this branch changes only the
`altimate-code` plugin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@hkaltai
hkaltai marked this pull request as ready for review October 29, 2026 08:20
hkaltai and others added 2 commits October 29, 2026 13:53
…shes, tighten docs and guard

Workspace skill copies are reconciled under a per-project lock and swapped with
rollback; a snapshot that cannot be read leaves copies alone; symlinked SKILL.md
and tenant-less manifests are not served. Failed background refreshes retry
hourly, --wait keeps another refresh's lock, the mode check avoids here-docs,
the warehouse guard checks chained commands, and the analyst agent no longer
reads .env. PRIVACY and README describe the workspace skill data flow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ned commands in the guard header

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

if [[ "$CMD" =~ ${PREFIX}(psql|trino|clickhouse-client|clickhouse|snowsql|mysql|sqlcmd|duckdb)([[:space:]]|$) ]]; then
# Interactive or help invocations without a query are left alone.
if [[ "$CMD" =~ (^|[[:space:]])(-c|--command|-e|--execute|-q|--query|-f|--file|-x)([[:space:]=]|$) ]] || [[ "$CMD" =~ (\<\<|\|[[:space:]]*(psql|trino|clickhouse|snowsql|mysql|duckdb)|\<[[:space:]]*[^[:space:]]+\.sql) ]]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: \< is a GNU/glibc word-start assertion, so this branch is always true on Linux

[[ ... =~ ]] compiles with glibc regcomp, where \< matches the start of a word. \<\< therefore matches the empty string at any word start, so the second condition fires for every command that reached line 43. On glibc systems every command-position psql, trino, mysql, duckdb, snowsql, sqlcmd or clickhouse-client is denied - including the read-only invocations this file promises to leave alone (psql --version, psql -h db). The allow 'psql --version' case in tests/warehouse-guard.sh cannot pass there. BSD regex (macOS) treats \< as a literal <, so behaviour also differs by platform. Match the heredoc/redirect forms with plain << / < instead of backslash-escaped ones.

# A client is only matched in command position (start, or after ; & | ( or sudo / docker exec),
# so file operations that merely mention a client name pass.
START='(^|[;&|(]|&&|\|\|)[[:space:]]*(sudo[[:space:]]+)?'
DOCKER='(docker|podman|kubectl)[[:space:]]+(exec|compose[[:space:]]+exec)[^;&|]*[[:space:]]'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: the docker branch is not anchored to command position

$START carries the (^|[;&|(]) anchor, but the $DOCKER alternative does not, so docker exec ... <client> matches anywhere in the string. A command that merely mentions one, e.g. git commit -m 'docker exec -i pg psql -c select 1', is denied, contradicting the comment above about matching only in command position. Wrap the docker branch in the same anchor.

find "$LOCK" -maxdepth 0 -mmin +10 -exec rmdir {} \; 2>/dev/null
if [ "$MODE" = "--wait" ]; then
# A refresh already in flight finishes first; this one then picks up anything newer.
for _ in $(seq 1 120); do mkdir "$LOCK" 2>/dev/null && break; sleep 1; done

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: this wait loop does not record whether the lock was actually acquired

If an in-flight refresh outlasts the 120 attempts, the loop falls through, the command runs workspace refresh concurrently with it, and line 45 then rmdirs a lock owned by the other process, letting a third refresh start. The stale-lock cleanup on line 38 only reclaims locks older than ten minutes, so after a crashed refresh the two-minute wait always ends unlocked and two refreshes write the same snapshot. Separately, seq is not installed on stock macOS, where the loop body never runs at all. Set a LOCKED=1 flag when mkdir succeeds and only rmdir in that case, and use a portable counter.

ids = list(manifest.get("skills", {}))
owner = (manifest.get("tenant"), str(manifest.get("apiUrl", "")).rstrip("/"))
except (OSError, ValueError, AttributeError):
return []

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: an unreadable snapshot is treated as another tenant and deletes every copied skill

return [] here - and signed_in_as() returning None when ~/.altimate/altimate.json cannot be read or parsed - makes sync() remove all marked .claude/skills/<name> copies. A manifest caught mid-write by a concurrent workspace refresh, or temporarily unreadable credentials, therefore wipes the team skills from the project. Because refresh-skills.sh --if-stale skips while .synced-at is under an hour old, they are not restored until the next stale refresh. This also contradicts the module docstring's 'a failure leaves existing copies as they were'. Return a sentinel (e.g. None) on read/parse failure and skip the removal pass instead of deleting.

MANIFEST = ".manifest.json"
SKILLS_DIR = os.path.join(".claude", "skills")
MARKER = ".altimate-workspace-skill"
SNAPSHOT_META = {MANIFEST, ".gitignore", ".synced-at"}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: SNAPSHOT_META is never used

Hidden files inside the bundle are already skipped by filename.startswith('.') in build_copy, so this constant is dead. Remove it or use it here so the snapshot-metadata invariant lives in one place.

printf ' "hookEventName": "SessionStart",\n'
printf ' "additionalContext": "The altimate-code plugin ships two skills in this session. (1) The `altimate-code` skill routes data-engineering work to the altimate-code CLI — column-level lineage, downstream-impact, cross-database validation, FinOps, PII from sampled rows, query cost attribution, schema diffs, dev-vs-prod diffing. In a project linked to an Altimate workspace it also answers from the shared skills, knowledge and memory of that workspace, so questions about team conventions, standards or best practices fit it too. It is not well-suited for pure file/code edits to dbt models and SQL files that do not touch warehouse state — native Bash/Edit/Write handles those faster. (2) The `review` skill runs the altimate-code dbt PR reviewer on dbt project changes (models/**.sql, schema.yml, dbt_project.yml, sources.yml, macros, snapshots, seeds). It emits a signed verdict envelope with column lineage, query equivalence, dbt anti-pattern detection, and PII screening — none of which native tools or a generic code-review skill can compute. When the user asks to review dbt / SQL / warehouse changes, this is the specialized reviewer available. For non-dbt code review (TypeScript, Python, Go), the `review` skill declines."\n'
if [ "$MODE" = "cli" ]; then
printf ' "additionalContext": "The altimate-code plugin ships two skills in this session. (1) The `altimate-code` skill describes the model-free data tools of altimate-code: column-level lineage, downstream-impact analysis, PII detection, data-diff between tables or databases, FinOps and query cost, query equivalence, dialect translation, dbt manifest and lineage, and read-only queries and schema inspection on connected warehouses. They reach Claude in two ways. When the session has the plugin MCP tools (named `mcp__plugin_altimate-code_altimate-code__*`), those are the tools. When it does not, because the organisation disallows MCP servers or the server did not start, the same tools run from the shell through the altimate CLI `tool run` subcommand, which also returns structured output without a second agent. Neither mode runs a second LLM, and calls are read-only unless the user approves writes. In a project linked to an Altimate workspace, the `workspace_context`, `workspace_skill` and `workspace_execute` tools (MCP, or `tool run` with `--workspace-tools`) give the team conventions, knowledge, shared skills, project memory and read-only queries on the workspace warehouse integrations. Long multi-step jobs such as dbt builds and migrations can be delegated to the altimate-code agent. Plain file edits to dbt models and SQL files need none of this. (2) The `review` skill runs the altimate-code dbt PR reviewer on dbt project changes (models/**.sql, schema.yml, dbt_project.yml, sources.yml, macros, snapshots, seeds). It emits a signed verdict envelope with column lineage, query equivalence, dbt anti-pattern detection, and PII screening, which native tools and a generic code-review skill do not compute. For non-dbt code review (TypeScript, Python, Go), the `review` skill declines. In this session the altimate-code MCP server is not available, so the following project guidance applies. Data work in this project: the warehouses and dbt project of this repository are connected to Altimate Code through its CLI. When a request needs warehouse data or schema, column lineage, downstream impact, PII checks, data diffs or warehouse cost, use the Altimate Code CLI instead of ad-hoc database clients: run `altimate-code tool context` once, then `altimate-code tool run <tool> --workspace-tools --args <json>`; find a tool with `altimate-code tool list --workspace-tools` and its arguments with `altimate-code tool schema <tool> --workspace-tools`. `tool context` also names the linked workspace and lists its team skills. Questions about the team conventions, definitions or workspace data start with `tool run workspace_context --workspace-tools`; warehouse reads through the workspace engine use `tool run workspace_execute --workspace-tools`. It uses the configured connections and is read-only by default. Long multi-step jobs (dbt builds, migrations, backfills) use `altimate-code run`. Code edits, docs, tests and git work that need no warehouse data or lineage use the normal tools.%s"%s\n' "$SKILLS_NOTE" "$RELOAD"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: the ~2.4 KB additionalContext text is duplicated

Line 57 repeats this entire string for MCP mode; the branches differ only in the trailing CLI-only guidance sentence. Two copies of a 2.4 KB prompt that already differ in intent will drift. Build the shared prefix once in a variable and append the mode-specific sentence plus $SKILLS_NOTE/$RELOAD.

5. For long multi-step jobs, or when you invoke **`/altimate-code:altimate <task>`** for work that needs the agent, Claude Code runs `altimate run "<your task>"` locally with the `builder` agent (or `analyst` for a data question when MCP is unavailable), which uses your configured LLM provider.
6. Warehouse queries and dbt commands run **locally under your credentials**. If the installed CLI predates the `tool` subcommand, the skill falls back to delegation.

Connections come from project and global `.altimate-code/connections.json` files and `ALTIMATE_CODE_CONN_*` environment variables. To pin a file for the MCP server, change the `args` in `.mcp.json` to `["mcp", "serve", "--connections", "/absolute/path/to/connections.json"]`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: this example drops --workspace-tools

Following it disables the linked-workspace MCP tools this PR adds: .mcp.json and tests/workspace-tools.sh both require --workspace-tools, and CHANGELOG 1.4.0 states the server starts with it. Show ["mcp", "serve", "--workspace-tools", "--connections", "/absolute/path/to/connections.json"].

Comment thread tests/workspace-tools.sh
grep -q "$tool" "$PLUGIN/skills/altimate-code/SKILL.md" || fail "SKILL.md does not describe $tool"
done

out="$(env -i HOME="$(mktemp -d)" PATH="/usr/bin:/bin" ALTIMATE_DATA_MODE=cli bash "$PLUGIN/hooks-handlers/session-start.sh")"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: this runs the real SessionStart hook against the caller's working directory

With env -i but no CLAUDE_PROJECT_DIR and no cd, the hook falls back to $PWD, so it syncs .claude/skills in the checkout the suite was started from. If that checkout has a linked .altimate-code directory it also starts a real background workspace refresh and can remove marked skill copies outside the temp dir. The other hook tests pin CLAUDE_PROJECT_DIR to a mktemp project; do the same here (and clean up the mktemp -d HOME).

@kilo-code-bot

kilo-code-bot Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Code Review Summary

Status: 9 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 8
Issue Details (click to expand)

WARNING

File Line Issue
plugins/altimate-code/hooks-handlers/refresh-skills.sh 51 seq is not installed on macOS, so the new LOCKED guard now makes --wait print "another refresh is still running" and exit 1 on every /altimate-code:refresh-skills run there; previously it fell through and refreshed.

SUGGESTION

File Line Issue
plugins/altimate-code/hooks-handlers/warehouse-guard.sh 45 The docker/podman/kubectl branch is not anchored to command position, so a command that merely mentions docker exec ... <client> (e.g. a commit message) is denied, contradicting the comment above it.
plugins/altimate-code/hooks-handlers/sync-workspace-skills.py 58 SNAPSHOT_META is still unused dead code.
plugins/altimate-code/hooks-handlers/session-start.sh 66 The ~2.4 KB additionalContext string is still duplicated between the CLI and MCP branches, and now carries seven %s placeholders that must be kept in sync by hand.
plugins/altimate-code/README.md 59 The --connections example still drops --workspace-tools, silently disabling the linked-workspace MCP tools.
tests/workspace-tools.sh 31 The hook under test still falls back to the caller's $PWD, so it can create/remove .claude/skills entries and start a refresh in the real checkout instead of a temp project.
CONTRIBUTING.md 94 Claims CLI mode applies when the installed build lacks mcp serve; data-mode.sh only checks PATH and the MCP policy settings, so such a build stays in MCP mode and fails to start (README:14 repeats the claim).
plugins/altimate-code/hooks-handlers/sync-workspace-skills.py 417 read_snapshot reads and parses the credentials plus every SKILL.md before the lock and again after it on the first sync; only a cheap "is there a snapshot" check is needed beforehand.
tests/test_sync_workspace_skills.py 211 The new manifest-attribution test is vacuous: its credentials are invalid, so it passes even if the tenant/apiUrl/account checks are removed.
Files Reviewed (18 files)
  • .gitignore
  • CONTRIBUTING.md - 1 suggestion
  • PRIVACY.md
  • plugins/altimate-code/CHANGELOG.md
  • plugins/altimate-code/README.md - 1 suggestion
  • plugins/altimate-code/agents/analyst.md
  • plugins/altimate-code/hooks-handlers/data-mode.sh
  • plugins/altimate-code/hooks-handlers/refresh-skills.sh - 1 warning
  • plugins/altimate-code/hooks-handlers/session-start.sh - 1 suggestion
  • plugins/altimate-code/hooks-handlers/sync-workspace-skills.py - 2 suggestions
  • plugins/altimate-code/hooks-handlers/warehouse-guard.sh - 1 suggestion
  • plugins/altimate-code/skills/altimate-code/SKILL.md
  • tests/data-mode.sh
  • tests/refresh-skills.sh
  • tests/session-start.sh
  • tests/test_sync_workspace_skills.py - 1 suggestion
  • tests/warehouse-guard.sh
  • tests/workspace-tools.sh - 1 suggestion

Fix these issues in Kilo Cloud

Previous Review Summary (commit d6d440c)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit d6d440c)

Status: 8 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 3
SUGGESTION 5
Issue Details (click to expand)

WARNING

File Line Issue
plugins/altimate-code/hooks-handlers/warehouse-guard.sh 45 \< is a glibc word-start assertion, so \<\< matches any word start and every command-position warehouse client is denied on Linux, including psql --version that the tests expect to pass.
plugins/altimate-code/hooks-handlers/refresh-skills.sh 41 The --wait path never tracks whether it acquired the lock; on timeout it runs a concurrent refresh and rmdirs another process's lock, and seq is absent on stock macOS so the wait loop never runs.
plugins/altimate-code/hooks-handlers/sync-workspace-skills.py 127 An unreadable/corrupt manifest (or unreadable credentials) is treated as another tenant and deletes every copied skill, contradicting the docstring; the hourly refresh gate can leave them gone for up to an hour.

SUGGESTION

File Line Issue
plugins/altimate-code/hooks-handlers/warehouse-guard.sh 33 Docker/podman/kubectl branch is not anchored to command position, so commands that merely mention docker exec ... <client> are denied.
plugins/altimate-code/hooks-handlers/sync-workspace-skills.py 40 SNAPSHOT_META is unused dead code.
plugins/altimate-code/hooks-handlers/session-start.sh 55 The ~2.4 KB additionalContext string is duplicated between the CLI and MCP branches.
plugins/altimate-code/README.md 59 The --connections example drops --workspace-tools, silently disabling the workspace MCP tools.
tests/workspace-tools.sh 31 The hook under test falls back to the caller's $PWD, so it can mutate/re-sync the real checkout instead of a temp project.
Files Reviewed (28 files)
  • .claude-plugin/marketplace.json
  • .gitignore
  • CONTRIBUTING.md
  • PRIVACY.md
  • README.md
  • plugins/altimate-code/.claude-plugin/plugin.json
  • plugins/altimate-code/.mcp.json
  • plugins/altimate-code/CHANGELOG.md
  • plugins/altimate-code/README.md - 1 suggestion
  • plugins/altimate-code/agents/analyst.md
  • plugins/altimate-code/commands/altimate.md
  • plugins/altimate-code/commands/refresh-skills.md
  • plugins/altimate-code/hooks-handlers/data-mode.sh
  • plugins/altimate-code/hooks-handlers/refresh-skills.sh - 1 warning
  • plugins/altimate-code/hooks-handlers/session-start.sh - 1 suggestion
  • plugins/altimate-code/hooks-handlers/sync-workspace-skills.py - 1 warning, 1 suggestion
  • plugins/altimate-code/hooks-handlers/warehouse-guard.sh - 1 warning, 1 suggestion
  • plugins/altimate-code/hooks/hooks.json
  • plugins/altimate-code/skills/altimate-code/SKILL.md
  • plugins/altimate-code/skills/review/SKILL.md
  • tests/data-mode.sh
  • tests/refresh-skills.sh
  • tests/resolve-cli.sh
  • tests/session-start.sh
  • tests/test_sync_workspace_skills.py
  • tests/warehouse-guard.sh
  • tests/workspace-mcp-fixture.py
  • tests/workspace-tools.sh - 1 suggestion

Fix these issues in Kilo Cloud


Reviewed by deepseek-v4.1-flash-1017 · Input: 86.7K · Output: 52.1K · Cached: 1.6M

…uring swaps, and judge warehouse clients by their own flags

Workspace skill copies are served only for the signed-in account (tenant, URL
and the CLI's credential digest), survive the CLI's snapshot swap, are never
written through a symlinked .claude, are removed when copying is turned off,
and carry a named marker. Refresh freshness is per account. The MCP mode check
follows Claude Code's policy rules (managed-mcp.json, managed-settings.d,
scoped plugin server name, serverCommand, merged allowlists, /mcp toggles by
git root), and CLI-mode guidance names the executable on PATH. The opt-in
warehouse guard checks each client call against its own query flags.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hkaltai and others added 3 commits October 30, 2026 09:46
…recognise its staging names

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…and partial reads

Skills are served only to a signed-in account for a manifest the CLI would
attribute; credentials or a snapshot that cannot be read change nothing, and a
manifest replaced mid-sync stops the removal pass. The shared mkdir lock is
renewed, taken over by rename and released only by its holder. BOM, symlink,
Windows and special-file handling now give the same copies as the CLI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…; junctions on every Python version

Each copy is swapped in only while the lock is held and the snapshot is the one
read and still the signed-in account's. Swap detection uses the staging
directory's mtime (Windows ctime is creation time). Junctions are refused at
every path via st_reparse_tag, a SKILL.md that is not a regular file skips that
skill, and marker lines split like the CLI's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# A refresh already in flight finishes first; this one then picks up anything newer.
LOCKED=
for _ in $(seq 1 120); do mkdir "$LOCK" 2>/dev/null && LOCKED=1 && break; sleep 1; done
[ -n "$LOCKED" ] || { say "Another workspace skill refresh is still running; try again when it finishes."; exit 1; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: seq is not installed on macOS, so the new LOCKED guard makes --wait fail there

seq ships with GNU coreutils, not macOS, so $(seq 1 120) expands to nothing and the loop body never runs. With the new [ -n "$LOCKED" ] check, /altimate-code:refresh-skills now prints "Another workspace skill refresh is still running" and exits 1 on every macOS run; before this change it fell through and refreshed. Use a portable counter (i=0; while [ "$i" -lt 120 ]; do ...; i=$((i + 1)); done) or jot.

Comment thread CONTRIBUTING.md
- **Command** — `plugins/altimate-code/commands/altimate.md` — `/altimate-code:altimate` slash command for explicit delegation.
- **Routing skill** — `plugins/altimate-code/skills/altimate-code/SKILL.md` — use the MCP tools when available, otherwise `tool run` (after `tool context`); delegate long jobs with `run`.
- **Analyst agent** — `plugins/altimate-code/agents/analyst.md` — read-only data analyst that works in both modes.
- **MCP registration** — `plugins/altimate-code/.mcp.json` — launches the local stdio server; builds without `mcp serve` fail to start it and the CLI mode applies instead.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: CLI mode does not apply when the build lacks mcp serve

data-mode.sh chooses the mode from command -v altimate-code and the MCP policy settings only; it never runs the CLI, so it cannot detect a build without mcp serve. Such a build stays in MCP mode, the server fails to start, and the CLI routing guidance is not added (the PR's "Known limitations" says the same). plugins/altimate-code/README.md:14 repeats the claim. Reword both to say the skill's tool run fallback applies instead, or probe altimate-code mcp serve --help at session start.

return False
if not os.path.isdir(target_root):
# Nothing to remove; create the directory only when there is something to copy.
snapshot = None if withdraw else read_snapshot(project)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: read_snapshot parses the whole snapshot twice on the first sync

On a project without .claude/skills this reads the credentials and every SKILL.md, discards the result, then repeats the same read after the lock at line 428. The pre-lock call only decides whether the directory should be created, so a cheap read_manifest(project) is not None check would avoid the duplicate work.

self.assertEqual(self.run_sync()[0], "changed")
self.assertFalse(os.path.exists(self.skill_path("staging-conventions")))

def test_snapshot_without_a_tenant_is_not_served(self):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: this test cannot detect a regression in the manifest check it names

The credentials written here (only altimateApiKey) make signed_in_as() raise Unreadable, so read_snapshot returns None and nothing is copied regardless of what owner_of does: deleting the tenant/apiUrl/account checks entirely would still pass. Keep the valid credentials from setUp, sync first, then strip tenant/apiUrl from the manifest and assert the existing copy is removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant