Parism
Analisador estruturado de saída de shell para agentes de IA — servidor MCP
Documentação
Parism
Refract the Shell. Every command, structured.
Um servidor MCP e biblioteca Node.js que permite que agentes de IA executem comandos de shell com segurança e recebam os resultados em JSON.
Documentação: SPECIFICATION · SECURITY · CHANGELOG
Visão geral
run({ "cmd": "ls", "args": ["-la", "src"] })
{
"ok": true,
"stdout": {
"raw": "drwxr-xr-x 2 user group 4096 Mar 06 09:23 src\n",
"parsed": {
"entries": [
{
"type": "directory",
"name": "src",
"permissions": { "owner": "rwx", "group": "r-x", "other": "r-x" },
"size_bytes": 4096,
"owner": "user",
"group": "group",
"modified_at": "2026-03-06T09:23:00"
}
]
}
}
}
rawsempre contém a saída original, intacta.parsedcontém a estrutura lida pelo parser. Comandos sem parser retornamnull.- Há parsers padrão para 43 comandos, e você pode adicionar parsers personalizados.
A saída do shell é feita para humanos. Se um agente tentar interpretá-la diretamente, frequentemente erra em espaços em nomes de arquivos, na ordem das colunas por SO (ps) e em cabeçalhos que variam por ambiente (df). O Parism detecta o SO, escolhe o parser correto e retorna o resultado interpretado.
Arquitetura
Agent (MCP client) Node.js code
│ stdio │ createEngine()
▼ ▼
┌──────────────────────────────────────────────────┐
│ Parism │
│ │
│ 1. Guard allowlist · paths · injection │──▶ blocked: ok=false, failure.kind="guard"
│ │ │
│ 2. Executor spawn (no shell), timeout, limit │──▶ exec error: failure.kind="exec"
│ │ │
│ 3. Redactor mask secrets in output │
│ │ │
│ 4. Parser OS-aware, 43 built-in + custom │──▶ no parser: parsed=null, raw kept
│ │ │
│ 5. Shaper filter · budget · evidence │
│ │ │
│ ├──▶ Result store (opt-in, in memory) │
└───────┼──────────────────────────────────────────┘
▼
{ ok, stdout: { raw, parsed }, failure?, review?, budget? }
Os comandos são executados diretamente como binários, sem passar pelo shell. Bloqueio, falha de execução e falha de parsing retornam respostas no mesmo formato, sem lançar exceções. O agente só precisa verificar failure.kind para decidir o próximo passo.
Início rápido
1. Instalação
npx @nerdvana/parism
Sem argumentos, executa como servidor MCP via stdio. Para compilar a partir do código-fonte:
git clone https://github.com/JinHo-von-Choi/parism
cd parism
npm install && npm run build
node dist/index.js
2. Registrar no cliente MCP
A maioria dos clientes aceita o formato abaixo diretamente.
{
"mcpServers": {
"parism": {
"command": "npx",
"args": ["-y", "@nerdvana/parism"]
}
}
}
A localização das configurações por cliente está nos seguintes documentos:
| Cliente | Documento |
|---|---|
| Claude Desktop | claude-desktop.md |
| Claude Code | claude-code.md |
| Cursor | cursor.md |
| Gemini CLI | gemini-cli.md |
| Codex CLI | codex.md |
| GitHub Copilot CLI | copilot-cli.md |
3. Primeira sequência de chamadas do agente
describe() 허용 명령, 파서, 가드 제한 확인
│
dry_run(cmd, args) 가드 통과 여부만 확인 (실행 안 함)
│
run(cmd, args) 실행하고 구조화된 결과 받기
│
├─ 출력이 크면 ──▶ run_paged(page=N) 또는 run(budget) + fetch_result
└─ 근거가 필요하면 ──▶ run(retain, evidence) + explain_result
Ferramentas
Ao conectar, 7 ferramentas são expostas.
| Ferramenta | Executa comando | Finalidade |
|---|---|---|
run | O | Execução padrão. Inclui opções de filtro, orçamento e justificativa |
run_paged | O | Lê saídas grandes em páginas de linhas |
describe | X | Verifica ambiente, comandos permitidos e informações do parser |
dry_run | X | Verifica antecipadamente se o guarda permitiria a execução |
explain_result | X | Consulta de onde um valor de um resultado arquivado veio no texto original |
fetch_result | X | Lê a próxima página de um resultado truncado por orçamento |
compare_results | X | Compara a diferença entre dois resultados arquivados |
explain_result, fetch_result, compare_results apenas leem resultados arquivados e não reexecutam comandos. Os arquivos ficam apenas na memória do processo do servidor, com limite de 2MiB por resultado, 32MiB no total, máximo de 16 itens, por 60 segundos. IDs desconhecidos, expirados, removidos ou não arquivados são rejeitados com motivos distintos.
run
| Parâmetro | Padrão | Descrição |
|---|---|---|
cmd | — | Nome do comando |
args | [] | Array de argumentos |
cwd | Diretório atual | Diretório de trabalho |
format | "json" | "json", "compact", "json-no-raw" |
includeDiff | false | Inclui mudanças no sistema de arquivos antes e depois da execução |
select where sort_by limit array | — | Filtros e projeção |
budget | — | Orçamento de tokens |
contract_version | "stable" | Se "next", adiciona metadados review |
evidence | "none" | "rows", "fields". Calcula a localização no texto original por campo |
retain | false | Arquiva o resultado na memória para uso por ferramentas subsequentes |
Se contract_version, evidence, retain, budget não forem especificados, o formato da resposta permanece igual ao da versão anterior.
format: "compact" reduz tokens ao dobrar resultados em lista com schema e rows.
{
"schema": ["name", "type", "size_bytes"],
"rows": [["src", "directory", 4096], ["main.ts", "file", 1200]]
}
run_paged
Use para comandos com saída grande, como ps aux, find, grep -r. stdout.parsed é sempre null e divide o texto original em linhas.
| Parâmetro | Padrão | Descrição |
|---|---|---|
page | 0 | Número da página, começando em 0 |
page_size | 100 | Linhas por página. Limite máximo: max_page_size (padrão 1000) |
O campo page_info da resposta contém total_lines, has_next, cache ({ hit, age_ms }). O mesmo comando reutiliza o resultado da primeira execução por 30 segundos.
describe
Sem argumentos, retorna version, allowed_commands, available_parsers, guard_summary, telemetry_enabled.
Se um comando for especificado, como describe({ cmd: "git" }), retorna apenas as informações desse comando, em até 2KB.
policy: subcomandos, flags e argumentos posicionais permitidos pelo guardaparser: formato lido pelo parser e campos do resultadoalternatives: argumentos alternativos para argumentos não suportadosexamples: exemplos de argumentos que passam no guarda atual
dry_run
Recebe cmd, args, cwd e retorna apenas a decisão do guarda, sem executar.
{ "would_pass": false, "reason": "command_not_allowed", "message": "Command 'rm' is not in the allowed list" }
O motivo do bloqueio é um dos seguintes: command_not_allowed, path_not_allowed, injection_pattern, arg_not_allowed.
Respostas e tratamento de falhas
result.ok === true ──▶ stdout.parsed 사용 (null이면 stdout.raw 사용)
result.ok === false ──▶ result.failure.kind 로 분기
├─ "guard" 가드가 차단함. 실행되지 않음
├─ "exec" 실행 실패. message에 stderr
├─ "parse" 파서 없음 (reason: "parser_not_found")
└─ "config" 필터 인자 오류 (unknown_field, type_mismatch)
{
"ok": false,
"failure": {
"kind": "guard",
"reason": "command_not_allowed",
"message": "Command 'rm' is not in the allowed list"
}
}
Para compatibilidade com versões anteriores, o campo guard_error também é enviado, mas a ramificação deve ser feita com failure.
Se o parser foi executado mas não conseguiu produzir um resultado, o motivo fica em stdout.parse_error e raw permanece como está.
parse_error.reason | Significado |
|---|---|
parser_exception | O parser lançou uma exceção |
schema_violation | Falha na validação de strict_schemas |
unsupported_format | Combinação de argumentos não tratada pelo parser |
unrecognized_output | Há linhas de dados, mas nenhum valor foi lido |
Argumentos não suportados
Cada parser declara o intervalo de argumentos que valida. Se um argumento fora desse intervalo for fornecido, o parser não tenta adivinhar e retorna unsupported_format; se houver um argumento que obtenha a mesma informação, ele é indicado em hint.
{ "reason": "unsupported_format", "hint": { "args": ["log", "--format=%h %s"] } }
| Entrada | Sugestão |
|---|---|
uname -r | ["-a"] |
git status -s --ignored | ["status", "--ignored"] |
kubectl get pods -o yaml | ["get", "pods", "-o", "json"] |
Comandos cuja saída já é JSON (kubectl get pods -o json, docker inspect) vão direto para parsed, sem parser.
Guarda
Quatro verificações são aplicadas em sequência para impedir que comandos malformados criados pelo agente sejam executados.
cmd + args
│
▼
[1] allowed_commands 목록에 없는 명령 ──▶ command_not_allowed
│
[2] allowed_paths cwd·경로 인자가 범위 밖 ──▶ path_not_allowed
│
[3] block_patterns ; $( ` && || | > >> < ──▶ injection_pattern
│
[4] arg restrictions node -e, npx --yes 등 ──▶ arg_not_allowed
│
▼
실행
- Lista de comandos permitidos: comandos que não estão em
allowed_commandssão rejeitados sem criar o processo. - Restrição de caminho: se
allowed_pathsestiver definido, argumentos que parecem caminhos (contêmcwd, começam com/ou.,~, ou que existem de fato, incluindo links simbólicos) são verificados. Se vazio, não há restrição de caminho. - Padrões de injeção: argumentos com metacaracteres de shell são rejeitados.
- Restrições por comando:
node -e,node --eval,node --input-type,npx --yessão bloqueados por padrão.
O guarda é uma defesa em nível de processo, não um sandbox de kernel. Para isolamento em ambientes não confiáveis, veja SECURITY.md.
Comandos suportados
43 comandos têm parser padrão. Os campos de resultado por comando podem ser verificados com describe({ cmd: "…" }).
| Categoria | Comando | Permitido por padrão |
|---|---|---|
| Sistema de arquivos | ls -l find stat du df tree | O |
| Processos | ps aux | O |
| Rede | ping curl -I netstat lsof -i ss dig | O |
| Texto | grep -n wc head tail cat | O |
| Git | git status git status --porcelain git log --oneline git diff git branch -vv | O |
| Implantação | kubectl get docker gh pr list helm list | O |
| Ambiente | env pwd which | O |
| Sistema | free uname id systemctl list-units journalctl apt list apt search brew list --versions | O |
| Pacotes | npm list | O |
| Pacotes | pnpm list yarn list | Requer permissão explícita (yarn também exige perfil build) |
| Build | terraform plan cargo tree | Perfil build |
| Controle de processos | kill | Requer permissão explícita |
| Windows | dir tasklist ipconfig systeminfo | Requer permissão explícita |
- Requer permissão explícita: o comando deve ser adicionado a
guard.allowed_commands. - Perfil build:
guard.profiledeve ser alterado para"build".cargoeyarnpodem executar wrappers ou scripts definidos pelo repositório, mesmo sendo comandos de consulta, por isso só são liberados nesse perfil.
Recursos avançados
Filtros e projeção
O array de nível superior do resultado do parsing (ls de entries, git log de commits, etc.) é filtrado no servidor para receber apenas o necessário.
parsed rows ──▶ where ──▶ sort_by ──▶ limit ──▶ select ──▶ response
{
"cmd": "ls", "args": ["-l"],
"where": [{ "field": "type", "op": "eq", "value": "file" },
{ "field": "size_bytes", "op": "gt", "value": 1000 }],
"sort_by": { "field": "size_bytes", "order": "desc" },
"limit": 10,
"select": ["name", "size_bytes"]
}
- Operadores:
eqneprefixcontains(string, número, booleano,null),gtgteltlte(número). Todas as condições devem ser atendidas. - Se houver vários arrays, use
arraypara escolher o alvo. - O resultado recebe
_summary: { total, matched, shown }estdout.rawé removido. - A ordenação é estável; linhas sem valor vão para o final.
- Em um diretório com 500 itens, usar
select: ["name","size_bytes"], limit: 50reduz o tamanho do resultado de 30.122 tokens para 725 tokens.
Orçamento de tokens
Ajusta o resultado ao orçamento definido e informa o que foi omitido e em que quantidade.
{ "max_tokens": 2000, "required_fields": ["path"], "overflow": "page" }
Agent Parism
│ run(cmd, budget, retain:true) │
│────────────────────────────────▶│ 실행, 파싱, 예산에 맞춰 자름
│◀────────────────────────────────│ budget, omission[], continuation.cursor
│ │
│ fetch_result(result_id, cursor) │
│────────────────────────────────▶│ 보관본에서 다음 페이지 (재실행 없음)
│◀────────────────────────────────│ 다음 행 + 새 cursor
│ ... cursor가 없을 때까지 반복
"budget": { "max_tokens": 2000, "measured_tokens": 1842, "budget_met": true },
"omission": [{ "stage": "budget", "rows_total": 206, "rows_returned": 138, "rows_omitted": 68 }]
- O orçamento define quanto do resultado já obtido será enviado. Não reduz o tempo de execução nem a quantidade coletada.
required_fieldse os campos de identificação de linha nunca são omitidos de nenhuma linha. Se não for possível mantê-los dentro do orçamento, a resposta falha em vez de enviar parcialmente.- Se o orçamento for menor que o tamanho mínimo da resposta (cerca de 1.200 tokens), a solicitação é rejeitada antes da execução com
budget_too_small. omission[].stageé um dos seguintes:capture,parse,projection,budget,privacy, permitindo distinguir linhas omitidas por orçamento das omitidas por problema no parser.- O tokenizador tem dois modos:
parism/approx(aproximado) ebyte(por caractere). A medição cobre apenas o JSON gerado pelo Parism e pode diferir da contagem interna de tokens do modelo. - O cursor está vinculado ao resultado e às condições da consulta. Cursors de outros resultados são rejeitados com
cursor_mismatch; cursors adulterados, comcursor_invalid.
JSON é maior que o texto original equivalente. Para ls -la com 200 linhas, o texto original tem 5.044 tokens e o JSON, 12.204. Para economizar tokens, use select, limit, format: "json-no-raw", budget juntos.
Consulta de justificativa
Responde "de onde veio esse valor no texto original" com intervalos de bytes.
run(cmd, { contract_version: "next", evidence: "fields", retain: true })
└─▶ review.result_id
│
explain_result(result_id, pointer: "/processes/0/pid")
└─▶ value, source_kind, source_spans [start, end), transform
{
"ok": true, "result_id": "r_...", "pointer": "/processes/0/pid",
"value": 1,
"source_kind": "derived",
"source_spans": [{ "source": "stdout", "start": 90, "end": 91, "line": 2, "transform": "parseInt" }],
"transform": "parseInt", "age_ms": 12
}
- Os intervalos são offsets UTF-8 em bytes sobre o texto original com segredos mascarados, no formato
[start, end). - Valores idênticos ao original usam
verbatim; valores transformados usamderived, com a transformação aplicada. - Os parsers que geram justificativa atualmente são
psegit status --porcelain. Campos de outros parsers retornamsource_kind: "none", com o motivo emwarnings. - A justificativa indica apenas o que o comando exibiu naquele momento; não é prova de que o valor é verdadeiro.
- Usar
evidenceoubudgetdesativa a transformação compact automática, pois em tabelas dobradas o alvo do ponteiro desaparece.
Os principais campos de review, presente quando contract_version: "next", são:
| Campo | Significado |
|---|---|
result_id | ID passado para ferramentas subsequentes |
parser_id / parser_version / schema_version | Parser e schema que geraram o resultado |
content_hash | Hash do texto original |
source_complete / parse_complete / representation_lossless | Se coleta, parsing e transformação terminaram sem perdas (true / false / unknown) |
privacy_transform | "none" / "masked" / "unknown" |
retained | Se está arquivado |
warnings | Motivo de incompletude ou ausência de justificativa |
Comparação de resultados
compare_results compara dois resultados arquivados com run(retain: true).
run(..., retain:true) ─▶ base_id ─┐
├─▶ compare_results(base_id, current_id)
run(..., retain:true) ─▶ current_id ┘ │
├─ comparable: false ─▶ refusals.reasons
└─ comparable: true ─▶ added / removed / changed
{ "comparable": false, "refusals": { "reasons": ["different command"] } }
- Argumentos opcionais:
keys,ignore_fields,strict. - Se um dos lados estiver incompleto, linhas ausentes não são tratadas como remoção; ficam pendentes em
partial.withheld_reasons. - Critério de identificação de linha: para git, caminho real do repositório e caminho do arquivo; para Kubernetes, context, namespace, kind e
metadata.uid. Saídas de tabela sem uid não são consideradas o mesmo recurso.psfica pendente porque PIDs podem ser reutilizados. - Se o mesmo identificador aparecer duas vezes, a comparação para com
duplicate_identity. - argv é comparado por hash e apenas valores mascarados são exibidos. Variáveis de ambiente são registradas apenas pelo nome.
Configuração
prism.config.json altera o comportamento do guarda e dos parsers.
~/.parism/prism.config.json 전역
│ 덮어씀
<cwd>/prism.config.json 프로젝트 (가드를 넓히지 못함*)
│ 덮어씀
PARISM_* 환경 변수
▼
최종 설정
* Para ampliar o guarda com configuração de projeto, defina "trust_project_config": true na configuração global.
{
"guard": {
"allowed_commands": ["ls", "git", "find", "grep", "env", "ps"],
"allowed_paths": ["/home/user/projects"],
"profile": "readonly",
"timeout_ms": 10000,
"max_output_bytes": 102400,
"max_items": 500,
"default_page_size": 100,
"block_patterns": [";", "$(", "`", "&&", "||", ">", ">>", "<", "|"],
"command_arg_restrictions": {
"node": { "blocked_flags": ["-e", "--eval", "-r", "--require", "-p", "--print", "--input-type"] },
"npx": { "blocked_flags": ["--yes", "-y"] }
},
"secrets": {
"env_patterns": ["TOKEN", "SECRET", "AUTHZ", "PASSWORD", "PASSWD", "CREDENTIAL"],
"output_redaction_enabled": false
}
},
"parsers": {
"strict_schemas": false,
"external_isolation": "worker",
"external_time_limit_ms": 500,
"external_memory_limit_mb": 128
},
"telemetry": {
"enabled": false
}
}
| Chave | Descrição |
|---|---|
guard.allowed_paths | Se vazio, não há restrição de caminho |
guard.profile | "readonly" (padrão) permite apenas subcomandos de consulta. "build" adiciona comandos de build e teste, como npm run, npm test, cargo build, terraform plan, docker compose ps. Como executam código do projeto, ative apenas em repositórios confiáveis |
guard.command_arg_restrictions | Mesclado com o padrão. Alterar apenas alguns comandos mantém as demais restrições padrão |
guard.command_policies | Substitui regras de subcomandos e flags por comando |
guard.secrets.env_patterns | Remove variáveis de ambiente com nome correspondente nos processos filhos |
guard.secrets.output_redaction_enabled | Se true, substitui valores que correspondem a output_patterns na saída por [REDACTED] |
guard.secrets.output_patterns | Se omitido, usa padrões padrão (tokens do GitHub, GitLab, AWS, Slack etc.). Para desativar, use [] |
parsers.strict_schemas | Se true, valida o resultado do parsing com schema Zod |
telemetry.enabled | Se true, adiciona o tempo por etapa na resposta e mostra estatísticas por comando em describe. Não é enviado externamente |
node, npx, yarn devem ser adicionados diretamente em allowed_commands e só funcionam no perfil build. npx recebe --no automaticamente.
Variáveis de ambiente
| Variável de ambiente | Alvo | Formato |
|---|---|---|
PARISM_ALLOWED_COMMANDS | guard.allowed_commands | Separado por vírgulas |
PARISM_ALLOWED_PATHS | guard.allowed_paths | Separado por vírgulas |
PARISM_TIMEOUT_MS | guard.timeout_ms | Inteiro |
PARISM_MAX_OUTPUT_BYTES | guard.max_output_bytes | Inteiro |
PARISM_MAX_ITEMS | guard.max_items | Inteiro |
PARISM_DEFAULT_PAGE_SIZE | guard.default_page_size | Inteiro |
PARISM_STRICT_SCHEMAS | parsers.strict_schemas | true ou 1 |
PARISM_ADAPTIVE_FORMAT_JSON | parsers.adaptive_format_threshold.json | Inteiro |
PARISM_ADAPTIVE_FORMAT_COMPACT | parsers.adaptive_format_threshold.compact | Inteiro |
PARISM_ADAPTIVE_FORMAT_JSON_NO_RAW | parsers.adaptive_format_threshold.json_no_raw | Inteiro |
PARISM_TELEMETRY_ENABLED | telemetry.enabled | true ou 1 |
Uso como biblioteca
Pode ser chamado diretamente do código Node.js, sem MCP.
import { createEngine } from "@nerdvana/parism/engine";
const engine = await createEngine();
const result = await engine.run("ls", { args: ["-la"] });
console.log(result.stdout.parsed);
createEngine()lê a mesma camada de configuração que o servidor MCP e anexa os parsers externos registrados. Para usar apenas arquivos específicos, usecreateEngine({ configPath: "…" }).- Opção
run:args,cwd,format,includeDiff,select,where,sort_by,limit,array,page,page_size. - Use
engine.describe("git")para ver informações de um único comando.
Parser personalizado
Você pode anexar parsers diretamente a comandos que não possuem parser padrão. Parism é exclusivo para ESM e o esquema usa zod 3.
npm install @nerdvana/parism zod@^3
# package.json 에 "type": "module" 필요
capture ──▶ init-parser ──▶ 기대값 작성 ──▶ test ──▶ add ──▶ inspect
(출력 저장) (스캐폴드) (사람이 검토) (재생 검증) (등록) (토큰 비교)
parism capture "htop -b -n 1" # 1. 실제 출력을 fixture로 저장
parism init-parser htop # 2. 파서 팩 스캐폴드 생성
# 3. fixture에 기대값과 reviewed_by를 직접 적는다
parism test ~/.parism/fixtures # 4. 저장된 출력으로 파서를 다시 돌려 차이 확인
parism add ./htop # 5. 등록. 재시작 없이 바로 사용
parism inspect "htop -b -n 1" # 6. raw / parsed / compact 결과와 토큰 수 비교
Os pacotes registrados são armazenados em ~/.parism/parsers/ e carregados automaticamente na inicialização do servidor.
Interface ParserPack
import type { ParserPack } from "@nerdvana/parism/types";
const pack: ParserPack = {
name: "my-command",
parse(raw, args, ctx?) { /* 구조화된 결과 반환 */ },
schema: { /* Zod 스키마 */ },
fixtures: [{ input: "...", args: [], expected: { /* ... */ } }],
acceptedFlags: { "-a": "bool", "-n": "value" }, // 선택: 검증한 플래그. 그 밖은 unsupported_format
acceptedPositionals: { max: 1 }, // 선택: 위치 인자 규칙
supports: (args) => args.length < 4, // 선택: 추가 지원 조건
headerLines: 1, // 선택: 머리 줄 수
noise: /^Total /, // 선택: 데이터가 아닌 줄
rowsKey: "items", // 선택: 행 배열의 키
};
export default pack;
Fixture e verificação de regressão
$ parism capture "ls -l src"
Fixture saved: ~/.parism/fixtures/ls-20261005-163909.json
$ parism test ~/.parism/fixtures
fixture 4개
검토된 기대값 1개 중 일치 0 · 변화 1
미검토 기대값 3개 (사람이 검토해야 계약이 된다)
매니페스트 오류 0개
...
ls-20261005-163909 (ls)
[parsed] 10건
/entries/0/name value 기대 "WRONG" → 실제 "cli"
Os valores esperados do fixture devem ser escritos no seguinte formato:
"expected": {
"parsed": { "entries": [ … ] },
"reviewed_by": "이름",
"note": "이 값이 맞는 이유"
}
- Ao capturar, segredos, caminhos domésticos e valores de argumentos como
--token=são mascarados, e o histórico de mascaramento é registrado emredactions. - Valores esperados sem
reviewed_bysão tratados como sugestões e não contam como falhas. - A comparação é uma correspondência completa. Se você escrever apenas alguns campos nos valores esperados, todos os demais serão reportados como
extra, portanto escreva no mesmo formato do resultado real da análise. parism testnão reexecuta o comando nem reescreve automaticamente os valores esperados.- Valores esperados baseados em evidências verificam apenas os ponteiros fornecidos. Se precisar de correspondência completa, use
evidence.exhaustive: true.
O formato do manifesto está em SPECIFICATION.md §5.2.4.
parism eval
Neste host, verifica-se se o comando se comporta conforme o esperado em três camadas.
| Camada | O que verifica |
|---|---|
execution | Se foi realmente executado. Distingue bloqueio por guarda (blocked) de falha de execução |
parse | Se foi lido estruturalmente. Distingue ausência de parser de falha de parsing |
task | Se cumpriu a tarefa. Tarefas que buscam algo inexistente só são bem-sucedidas se não encontrarem |
parism eval # 전체 시나리오
parism eval execution-parse # 시나리오 하나
parism eval --verbose # 모든 항목 출력
Se houver qualquer item diferente do esperado, o código de saída é 1. Itens sem valor esperado são excluídos da agregação.
Isolamento de parsers externos
Os pacotes registrados são executados em threads de worker separados por pacote (parsers.external_isolation: "worker").
- Se uma chamada exceder
external_time_limit_ms(padrão 500ms), se o worker morrer ou se o heap V8 excederexternal_memory_limit_mb(padrão 128MB), isso é reportado comoparser_exception. Depois disso, durante um tempo de espera que aumenta de 2 segundos até no máximo 30 segundos, o pacote responde com falha imediata, e o servidor continua operando. - O valor de retorno de
parse()deve ser clonável estruturalmente. Se contiver funções, Promises ou Symbols, éparser_exception. - A saída de
consoledentro do pacote vai para stderr. - O custo de clonagem por chamada é de aproximadamente 0,1ms para entrada de 20 linhas e aproximadamente 1,6ms para entrada de 500 linhas.
- Para executar na thread principal, defina
"parsers": { "external_isolation": "none" }na configuração global.
O isolamento por worker é isolamento de falha, não um sandbox de segurança. O worker tem os mesmos arquivos, rede e permissões de variáveis de ambiente que o servidor. Se precisar usar pacotes não confiáveis, execute todo o Parism dentro de um contêiner ou VM.
Comandos CLI
| Comando | Descrição |
|---|---|
parism | Executa o servidor MCP (stdio) |
parism capture "<command>" | Refina o resultado da execução e salva como fixture |
parism init-parser <name> | Gera scaffold de pacote de parser (parser.ts, schema.json, fixtures/) |
parism test [dir] | Reproduz fixtures offline e reporta diferenças. Se houver fixtures quebrados, código de saída 1 |
parism add <path> | Registra o pacote de parser em ~/.parism/parsers/ |
parism inspect <command> [args...] | Comparação raw / parsed / compact e contagem de tokens |
parism eval [scenario] | Avalia o comportamento do host em três camadas |
Se você dividir os argumentos como parism inspect ls -l /path, eles são passados diretamente. Se fornecidos como uma única string como parism inspect "ls -l /path", eles são divididos por espaços, portanto aspas e espaços consecutivos não são preservados.
Ao atualizar de 2.0.x para 2.1.0
Se você chamar apenas run via MCP, não há nada para mudar. Os nomes das ferramentas permanecem os mesmos e três ferramentas (explain_result, fetch_result, compare_results) foram adicionadas. Apenas nos casos abaixo você precisa ajustar código ou configuração.
| Alvo | Antes | 2.1.0 |
|---|---|---|
| Autores de ParserPack externo | contract.noise, rowLine, acceptedValues na thread principal RegExp | Descritores calculados pelo worker. Se precisar do método antigo, use parsers.external_isolation: "none" |
Chamadores de toCompact(), parism inspect | Retorno de unknown | CompactOutcome ({ok:true,value} ou {ok:false,reason,message}) |
Configuração omitindo guard.secrets.output_patterns | Padrão não aplicado | Padrão aplicado. Para desativar, use output_patterns: [] |
Usuários de git status --porcelain | Alvo de aviso de failure.hint | Formato suportado. Parse como array de entries |
| Código que salva itens porcelain diretamente | xy, index, worktree, path, orig_path | Campo quoted adicionado (só tem valor no modo linha) |
A mudança do valor padrão de output_patterns é uma correção de segurança. Antes, se essa chave fosse omitida, mesmo com o mascaramento de saída ativado, tokens nas formas sk-, ghp_, AKIA, xoxb-, glpat- eram expostos diretamente.
Escopo
- Parism não substitui o shell. Ele executa comandos existentes e transforma a saída em estrutura.
- Ao consultar, retomar leitura ou comparar resultados arquivados, os comandos não são reexecutados. Resultados expirados precisam ser reexecutados.
- A comparação ocorre apenas entre dois resultados fornecidos pelo chamador. Não há monitoramento periódico.
- O orçamento de tokens é baseado no JSON criado pelo Parism. Não garante a contagem real de tokens feita pelo modelo.
Feito por Jinho Choi | Me pague um café